views:

646

answers:

5

Ruby on Rails does not do multithreaded request-responses very well, or at least, ActiveRecord doesn't.

The notion of only one request-response active at the same time can be a hassle when creating web applications which fork off a shell-command that takes long to finish.

What I'd like are some of your views on these kinds of setups? Is Rails maybe not a good fit for some applications?

Also, what are the current state of affairs in regard to concurrency in Ruby on Rails? What are the best practices. Are there workarounds to the shortcomings?

+3  A: 

Rails currently doesn't handle concurrent requests within a single MRI (Matz Ruby Interpreter) Ruby process. Each request is essentally wrapped with a giant mutex. A lot of work has gone into making the forthcoming Rails 2.2 thread-safe, but you're not going to get a lot of benefit from this when running under Ruby 1.8x. I can't comment on whether Ruby 1.9 will be different because I'm not very familiar with it, but probably not I'd have thought.

One area that does look very promising in this regard is running Rails using JRuby, because the JVM is generally acknowledged as being good at multi-threading. Arun Gupta from Sun Microsystems gave some interesting performance figures on this setup at RailsConf Europe recently.

John Topley
+1  A: 

If what you run at the shell is not necessary for the rendering of the page (e.g. you're only triggering maintenance tasks or something), you should start them as background processes. Check out starling and workling.

If this doesn't apply to your situation, you'll have to make sure multiple instances of your app servers run. Traditionally people would start multiple instances of Mongrel. But now I'd say the easiest way to have a solid setup is by far using Phusion Passenger. It's an Apache module that lets you easily specify how many instances (min and max) of your app servers you want to have running. Passenger does the rest. And if I recall correctly, it doesn't do stupid round robin for dispatching requests. I think it's by availability.

webmat
+3  A: 

Matz's Ruby 1.8 uses green threads, and Matz's Ruby 1.9 will use native O/S threads. Other implementations of Ruby 1.8, such as JRuby and IronRuby, use native O/S threads. YARV, short for Yet Another Ruby VM, also uses native O/S threads but has a global interpreter lock to ensure that only one Ruby thread is executing at any given time.

Alan Hecht
+1  A: 

Ruby 1.9 is adding lightweight Fibers:

http://www.infoq.com/news/2007/08/ruby-1-9-fibers

Alex Miller
+2  A: 

Neverblock allows for non blocking functionality without modifying the way you write programs. It really is an exciting looking project, and was backported to work on Ruby 1.8.x (it relies on Ruby 1.9's fibers). It works with both PostgreSQL and MySQL to perform non-blocking queries. The benchmarks are crazy...

Zach