Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Possible Duplicate:
How do you do Load Testing and Capacity Planning for Web Sites

Hey guys I had a question regarding scalability for my RoR application.

We have been optimizing our application over the last few days and after running, notice that our application times out after maybe 1000 hits in 30 seconds we experienced massive timeouts. In the 1 minute test apparently 74% of users would have timed out.

Look at the performance of my website:

Not saying that our website will in any way experience this now, but I wish to design the infrastructure to handle this.

What is normally done in this situation? Currently we have one web server and one database server. Would load balancing be the route to go?

share|improve this question

marked as duplicate by Michael Hampton, growse, Ward, Scott Pack, HopelessN00b Sep 26 '12 at 23:44

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

There are a lot different ways to improve the performance of your app. You're already doing one, optimizing. Especially if you start optimizing queries (ie fixing for n+1 queries). There are 3 other areas I would look into as well. Scaling vertically & scaling horizontally (, and the interpreter.

I like to scale horizontally first, at least a little bit. Having 2 app servers and a load balancer will increase the number of requests you can handle, and I like this approach initially because one app server is a single point of failure. Although in this situation the load balancer becomes a single point of failure. You could run 2 LBs for redundancy, but I that's a little outside the scope of your question.

After that, I would scale vertically. If you are running VMs like AWS EC2 instances, this is as simple as moving from say a m1.small to a c1.medium. Many other cloud providers have different ways to move up to larger servers. If you are running on your own hardware, benchmark your app and see where the bottleneck is (you should probably do this regardless, and do it first). If the bottleneck is memory, just upgrade the memory on your server and retest it. Then you may find the next bottleneck is the CPU, so you'll need to upgrade it.

The other area you should consider is the Ruby interpreter you are using. If you are using MRI (the default ruby interpreter), your leaving a lot of performance on the table. MRI is great for development, but in a traffic heavy site, I wouldn't use it if I could avoid it. MRI uses a Global Interpreter Lock (GIL) which basically makes your app single threaded. I could be wrong, but from my understanding, every process needs its own copy of the app in memory. So if you have 8 workers serving requests, your app will take up 8 times the memory.

There are several other Ruby interpreters out there like JRuby, and Rubinius. I don't know a lot about Rubinius, but from my understanding, it does away with the GIL and is a great alternative for MRI from a performance stand point.

I am a big fan of JRuby though. If you haven't already guessed, JRuby is a Ruby interpreter written in Java and Ruby. It's very stable and leverages the JVM, so you get native concurrency. And if you chose to go with Java 7, invokedynamic can inline method calls after the JVM warms up, and increase performance of JVM languages just like it would native Java code. With JRuby, instead of needing a new copy of the app in memory for every process, it uses threads which share a single copy of the app in memory.

If you do decide to go with JRuby, look into Torquebox which is an awesome application server built on top of JBoss. The lead developers for JRuby were recently hired by Red Hat, which already employed the developers for JBoss and Torquebox, so I imagine there is a lot of communication between these 3 groups.

Generic benchmarks are practically useless, but all the real benchmarks I've seen and heard about on real production apps comparing MRI to JRuby, the performance increase is absurd. I don't know if you'll get the same gains from Rubinius, but it may be easier to migrate to Rubinius than JRuby.

share|improve this answer
I missed the part in the title where you are using passenger. If you want to continue using passenger you aren't going to be able to use JRuby. You could also check Ruby Enterprise Edition (REE). I haven't ever looked for comparisons for REE vs Rubinius so I can't suggest one over the other. But I should mention that both REE and Rubinius currently only support 1.8.7. If you go the JRuby route, you'll have support for both 1.8.7 and 1.9.3. If you use JRuby 1.6.x you'll have to specify 1.9 mode. JRuby 1.7 will use 1.9.3, and the RC should be available in a few days. – Brandon Sep 21 '12 at 5:14
Thanks a lot for your reply. I have removed Passenger and have opted for your load balancing point. That was a though I had before and just never though about it again until you mentioned it. What I think i will also be doing is utilizing Unicorn with Capistrano. – Dani Cela Sep 22 '12 at 19:37
We've been using unicorn in production for a while now and it has served us pretty well. I'm trying to get our massive code bases converted to use Jruby/Torquebox right now, but I don't know if we'll ever transition. In the mean time, there has been some talk about switching to rainbows or puma, but I doubt that will happen anytime soon either. – Brandon Sep 23 '12 at 20:06

Not the answer you're looking for? Browse other questions tagged or ask your own question.