Tweaking Mod_Rails for speed and performance
I’ve recently made the switch Mongrel to Mod_Rails (aka Passenger) for hosting fluidsyntax.com and am very pleased with the results. The site is just as quick, but consumes almost half the memory under normal load – almost cutting the hosting costs in half!
One of the aspects which is so desirable about Mod_Rails is the speed with which you can deploy new sites due to the minimal configuration needed. In fact, to get a site running in the first place is pretty much as simple as just creating an apache vhost file to hook your site up. However, there are a couple of options which should be given consideration if you’re wanting to optimise your setup for your needs.
Unlike Mongrels which are always alive (or should be, at least!), Passenger spawns or kills processes as they’re needed or finished with. While this does make it consume considerably less RAM in general, it also means that if your site isn’t getting a lot of traffic, people will nearly almost find that their first request to your site is slowed down while Passenger spawns a new process.
First, second and third requests
The first request (before Passenger has started) is the most noticeable as this kicks the Passenger Spawn Server into life. This, in turn, loads the Framework spawner and Application spawner which load up Rails and your app. The second request (assuming it happens soon after the first) is very quick because all three spawners are still alive and waiting.
Fast-forward 5 mins with no traffic to your site and you’ll find that the Spawn Server is still running but the App and Rails processes have been killed (because 300 seconds is the default). That’s to be expected – Passenger is just cleaning up shop and trying to be efficient. But, if you reload the page, you’ll find it’s a little faster than the very first request was, but a little slower than the second request.
This is where the amount of traffic your site sees will have an effect on how your site runs. Surprisingly, under the default Passenger config, sites which receive regular traffic will have faster response times than ones which don’t.
Tweaking it
First up, make sure you’re using Ruby Enterprise Edition from Phusion nl (why, oh why ‘enterprise edition’?!) as this will give ruby itself a speed boost and that you’ve got the latest version of both that and Passenger installed.
Next, in your Apache config, it’s just a matter of adding a couple of settings…
PassengerPoolIdleTime 99999999
PassengerMaxPoolSize 4PassengerMaxPoolSize is the maximum number of Rails or Rack instances which can be simultaneously active. The default value is 6 which is a little high for a small vps server with 256mb of RAM. Phusion reccomends a value of 2 for 256mb servers but I’ve opted for a little higher because FluidSyntax is on a 360mb linode which only runs mod_rails powered sites and so it’s okay for nearly all RAM can be consumed by Passenger when it’s needed.
PassengerPoolIdleTime is the number of seconds an app needs to be inactive before it’s process is killed. Setting this to an insanely high number such as 99999999 basically means the app process will never be killed and will always be available – making it act more like a mongrel process. Phusion has mentioned in their blog that in a soon to be released future version of Passenger, you’ll be able to set PassengerPoolIdleTime to 0 to create the same effect.
Changing the PassengerPoolIdleTime like this will completely remove that slightly slower third request issue which I explained earlier because the process will always be waiting. If your site gets more regular traffic, you needn’t set the idle time so high, but 300 is still a low default in my opinion.
Start ’em up!
When you deploy a new release using capistrano and restart Passenger, you could also create a task to hit your site and start the Passenger spawners up:
task :kickstart do
run "curl -I http://www.yourdomain.com"
endThen no-one has to experience that slow first request, either!
Hosting multiple sites which use different versions of Rails
While it won’t slow your apps down, if you’re hosting multiple sites which use different versions of Rails, not surprisingly, Passenger will spawn a new FrameworkSpawner for each version. On my setup, each FrameworkSpawner consumes 32mb of RAM, so you could easily waste a considerable amount of RAM. If possible, get them all on the same version and you’ll free up that highly valued RAM so it can be used elsewhere.

