Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there still benefits to running JRuby vs. the latest MRI with Puma?

Tags:

ruby

jruby

puma

mri

I'm considering updating our ruby interpreter to JRuby, it's been quite a headache because we've had to remove any 2.x specific syntax from our app and resort to ruby 1.9.3 compatibility. Which isn't the end of the world.

When it came time to run the app, I found out that we cannot use Puma in clustered mode. The question is, given all the fixes and changes to MRI in the past few years, are the benefits of having "real threads" still valid?

update

To make this more objective, the question is, "Does the latest version of MRI negate the need to adopt JRuby to achieve the same benefits that native threads give you?"

like image 730
JP Silvashy Avatar asked Sep 23 '14 23:09

JP Silvashy


3 Answers

Does the latest version of MRI negate the need to adopt JRuby to achieve the same benefits that native threads give you?

The answer is no. It does not negate the need, and it depends on your application as mentioned in other answers.

Also, JRuby does not allow you to run in cluster mode, but that is not really a problem in regards to your question, because it is multithreaded and parallel. Simply run in Single mode with as many threads as you need. It should be perfectly fine, if not even more lightweight.


Let me give you some references that give more insight and allow you to dig further.

This answer discusses experiments with MRI and JRuby testing concurrent requests using Puma (up to 40 threads). It is quite comprehensive.

The experiments are available on GitHub, MRI and JRuby.

The caveat is that it only tests concurrent requests, but does not have a race condition in the controller. However, I think you could implement the test from this article Removing config.threadsafe! without too much effort.

The difference between JRuby and MRI is that JRuby can execute code in parallel. MRI is limited by the GIL and only one thread at a time can be executed. You can read more information about the GIL in this article Nobody understands the GIL.

The results are quite surprising. MRI is faster than JRuby. Feel free to improve and add race conditions.

Note that both are multi-threaded and not thread safe. The difference really is that MRI cannot execute code in parallel and JRuby can.


You might be tempted to say why I answer "No" if the experiment shows that MRI is faster.

I think we need more experiments and in particular real world applications.

If you believe that JRuby should be faster because it can execute code in parallel then reasons could be:

  • The experiments should be executed in a highly parallel environment to be able leverage the potential of JRuby.
  • It could be the web server itself. Maybe Puma does not leverage the full potential of JRuby. MRI has a GIL, so why is it faster than JRuby in handling requests?
  • Other factors might be relevant that are more in depth and we did not discover yet...
like image 174
Ely Avatar answered Nov 06 '22 22:11

Ely


Really depends on your scenario with the web-server (which you should have the very best understanding) ... case you feel your production is just serving about fine under MRI than you probably do not have that much concurrency around. puma's README pretty much explains what you get under MRI compared to Rubinius/JRuby :

On MRI, there is a Global Interpreter Lock (GIL) that ensures only one thread can be run at a time. But if you're doing a lot of blocking IO (such as HTTP calls to external APIs like Twitter), Puma still improves MRI's throughput by allowing blocking IO to be run concurrently (EventMachine-based servers such as Thin turn off this ability, requiring you to use special libraries). Your mileage may vary. In order to get the best throughput, it is highly recommended that you use a Ruby implementation with real threads like Rubinius or JRuby

... so in one sentence: ** you can have multiple threads under MRI, but you have no parallelism **

like image 24
kares Avatar answered Nov 06 '22 22:11

kares


IMHO It depends on what your application does.

I've tested both MRI/YARV and JRuby on my Rails application. Since most of what the app does is route HTTP requests, fetch from DB, apply simple business logic and write to the DB, parallelism isn't much of an issue. Puma on MRI does handle multi-threading for blocking IO operations (DB, API). Tasks that fall off this scope (image processing, crunching report data, calls to external APIs, etc.) should probably be handled by background jobs anyway (I recommend https://github.com/brandonhilkert/sucker_punch).

Depending on your deployment needs memory consumption might be more of an issue and JRuby is very hungry for memory. Almost 2x memory in my case.

If you're deploying your application on Heroku you might find that you get more bang for the buck by being able to run 2 instances concurrently on 1 dyno.

like image 22
Jim Avatar answered Nov 06 '22 22:11

Jim