Thursday, June 14, 2007

Rails threads vs. the Mongrel pack

Skip to the bottom if you have an aversion to reading.

I was very dissapointed to find out that Rails is not thread safe. Well, that's not totally true but I'll come back to that. What this means is that we cannot put every request to our rails application in it's own thread. Every request needs to line up and wait for rails to proccess it.

Using your out of the box script/server command this can be problamatic.

Imagine you can only buy the newspaper one page at a time, and you have to buy it from your freiendly neigherhood homeless person. Now this may not be so bad assuming you are the only person trying to read the newspaper.

But now the newspaper is getting popular, and there are 5 other people want to read the paper as well. It's still ok until Mary the town gossip spends 30 seconds buying her paper. Now everyone unfortunate enough to try and get a page during this time will have to wait those 30 seconds.

Mongrel to the rescue, sorta. So now instead of one homeless person we have a pack of homeless people (pack of mongrels). If one is slowed down by the town gossip you have other homeless people waiting to sell you that same page of the paper.

But there is a catch, you and all your fellow newspaper readers are blind (ironic, I know) and thus you can't see what homeless person has the shortest line. Lucky for you the native american girl Apache22 is willing to direct you to what she thinks is the best line. Unfortunatly she is not that great at this (through no fault of her own) and she can only tell when a line is in really bad shape.

As a concerned newspaper distributer what do we do? Round up more mongrels, but they come at a price. Adding more mongrels means more memory you will have to allocate for them. Each one is an entire Rails process. Depending on the app you are looking at 50-200 MB each. Whew, that sounds like I have to do some math, and I hate to think, is there an easier way?

If Rails were thread safe we could spawn a thread (homeless newspaper seller) for every request that comes in. Threads use much less memory then processes so we're not so worried about memory consumption.

But Rails is thread safe! Yes, I think it is, however is your application? And all those nifty plugins you installed? Thread safety is something we have to think about when developing, and we don't want our developers to have to think any more then they already do.

Can't we just kill all the people who are too slow? That's sick, but what we can do is make sure that all of our requests are served in a similar amount of time. It should be pretty obvious that most page requests should be returned in a matter of seconds, but if we are using AJAX to run a fatty report or search, that may not have crossed our minds. After all, that's why we have spinner.gif.

Is there a way to run a long process in the background? Of coarse, http://backgroundrb.rubyforge.org to the rescue. You will have to setup an observer on the client side that keeps asking the server if the job is done yet, but those requests will be small and fast.

So that's all. Let's review:

Threads:
- Applications need to be thread safe
- Small memory footprint

Processes (Mongrels!):
- Slow requests can hold up faster ones
- Larger memory footprint (~50-200MB)
- Architect needs to determine how many mongrels to run

Conclustion:
After reviewing the facts, threads are not as cool as I thought they were.

This is a gotcha more then a defect with rails.

Gotcha:
Rails does not run with threads by default. If you have actions that take a long time to process, you may ruin your performance long before anything else (database, disk I/O) starts to effect you application.

No comments: