Process, Threads and Async Ruby

Tram Ho

Ruby interpreter uses a single process by design. This means on your modern 8 core cpu, your script is going to use only 1/8th of your processing power at best. In this article, we’ll see more about multi-threaded and multi-process ruby.

Using multiple threads

Matz ruby interpreter uses GIL (Global Interpreter Lock), thus it only lets one thread to run at a time. So, in cpu bound tasks, there is no benefit of using multi thread, and it’ll yield no benefit for you (in ruby).
First, let’s take this example to calculate Fibonacci number. It’s totally a cpu bound task.

Let’s run it now using 10 threads.

On an ideal world, we’d hope tenfold performance increase. But,

So, what’s the benefit of using threads then?
The answer is, None (if you’re trying to solve a cpu bound problem).
But, if you’re trying to solve an IO bound issue, then threads will speedup your performance a lot.

Example: Performing HTTP requests with multiple threads

Imagine a scenario, where we have a method that checks if it can access some websites and responds back with HTTP status code.

Now, let’s rewrite the code to use multiple threads to do the job

That is a huge improvement over our single threaded implementation. On the plus side, running multiple threads don’t increase memory usage exponentialy like using multi-process.

Benefits

  1. Speedup for blocking operations
  2. Variables can be shared/modified (beaware of deadlocks)
  3. No extra memory used

Cons

  1. Much harder to debug

Using multiple processes

Remember our fibonacci implementation from #threads section.

We’ll now try to run this with multiple process instead of threads.
The re-written function will be

now, let’s see the benchmark.

So, compared to 40 sec, it’s using 18 sec. Which is a great improvement. Note the memory usage

This implementation is using 10 times higher memory. Which is the tradeoff.

Benefits

  1. Speedup through multiple CPUs
  2. Speedup for blocking operations
  3. Variables are protected from change
  4. Child processes are killed when your main process is killed through Ctrl+c or kill -2

Cons

  1. Memory usage will be higher.

Summary

It’s best described in this excellent article from Eqbal Quran .

In conclusion, we can say, there is not end all be all solution on which is best. We have to understand the workload and choose the best solution for our problem.

Things to study

Async Horror

Asynchronous Ruby -by Samuel Williams

Reactor Pattern

Parallel Gem

GIL – Global Interpreter Lock

Nobody understands GIL

Multiprocessing in ruby

Working with threads in ruby

Async Gem

Parallel Gem

Share the news now

Source : Viblo