Friday, December 9, 2011

Ruby (and Rails) scalability?

Recently I wrote about Node.jsperformance, comparing it to my (still non-public, sorry!) Objective-C based libµhttp wrapper and Apache on my main development machine of the time, a MacBook Pro.

Node.js did really well on tasks that have lots of concurrent requests that are mostly waiting, did OK on basic static serving tasks and not so well on compute-intensive tasks.

Having developed an interest in minimal web-servers, I wondered how Sinatra and, by association, Ruby on Rails would do.

For Sinatra I used the scanty blog engine and the basic "Hello World" example:

require 'sinatra'

get '/hi' do
  "Hello World!"

For Ruby on Rails, I used the blog tutorial "out of the box", invoking it with "rails s" to start the server. In addition I also had RoR just serving a static file instead of the database-backed blog. All this on my new dev machine, a 2011 MacBook Air with 1.8 GHz Intel Core i7 and 4 GB of DRAM. I also discovered that httperf is a much better benchmark program for my needs than ab. I used it with 100 requests per connection, a burst length of 100 and a sufficient number of connections to get stable results without taking all day.

Platform# requests/sec
Sinatra Hello World357
Ruby on Rails static page312
Sinatra scanty blog101
Ruby on Rails blog17
This seems really slow, even when doing virtually nothing, and absolutely abysmal when using the typical RoR setup, serving records from an SQL database via templates. I distinctly remember my G5 serving in the thousands of requests/s using WebObjects 6-7 years ago.

Is this considered normal or am I doing something wrong?


Jonah said...

That is very slow. I hesitate to speculate too much about your app configuration but one place to start is to check which rails environment you stared your server in. `rails s` will default to the development environment which is very handy during development but completely useless for determining what sort of load the framework can support. Among other things the development environment configuration sets `config.cache_classes` and `config.action_view.cache_template_loading` to false by default. That means that on every request to a development environment the server not only re-renders the view templates from scratch but also reloads every class it uses to do so! Very convenient when it allows you to edit a class and pick up the changes on the next request without requiring a server restart but no way to measure the performance of your application. Use `rails s -e production` to start the app using your production environment (environment settings are defined in `config/environments/*.rb`) and see what a difference that makes.

Marcel Weiher said...

Hi Jonah, thanks for the tips. I had looked at 'production' before, but it seems to assume that you will then create a whole production environment, which seems a little overkill. I'll see what I can do with your advice.