I installed Phusion Passenger a few weeks ago to get a production environment up and running for my Rails app. It was super easy to install and felt like magic. I checked off the item on my TODO and moved on. After all it didn’t say “YOUR APP WILL BE SLOW AS HELL IF YOU DON’T READ THIS MANUAL!!!” in their documentation. Well…it was too slow…and here’s how I fixed it.
Referencing the Phusion Passenger User Guide I was able to make changes that made my app run about 10 times faster. If you want to do this in 15 minutes, read this article. If you have a few hours, read through the user guide and experiment. My hardware setup is a 256MB Ubuntu VPS at my favorite hosting company – Slicehost.
The following are global settings I added to my httpd.conf:
RailsSpawnMethod smart PassengerUseGlobalQueue on PassengerMaxPoolSize 2 PassengerPoolIdleTime 0 PassengerMaxRequests 1000 RailsAutoDetect off RailsAppSpawnerIdleTime 0 PassengerStatThrottleRate 5
RailsSpawnMethod smart/smart-lv2/conservative
This can speed up the spawn time tremendously (by as much as 90%) if your app is compatible. However, some Ruby on Rails applications and libraries are not compatible with smart spawning. Set your configuration to smart spawning and if your app works, then you are all good. If not, use another spawning method.
PassengerUseGlobalQueue ON/OFF
Turning this option ON tells Passenger to add requests to a global queue when your Rails instances are busy. As soon as an instance becomes available it will grab a request from the queue. If the option is OFF, each process will maintain its own queue. Localized queues can hurt you if an instance is processing a 60-second request and Passenger adds a 1-second request to the instance’s queue. ( Imagine waiting in a 10 person non-express line at Whole Foods when all you want is a bottle of water ). Therefore, it only makes sense to turn this OFF for the 5% performance gain if all of your requests take about the same amount of time.
PassengerMaxPoolSize INTEGER
This simply says how many application instances Passenger is aloud to Spawn. The default is 6 but the user guide recommends 2 for a 256MB slice so that’s what I went with. More could consume a lot of memory and crash my server. You can use 30 if you have 2GB of RAM.
***PassengerPoolIdleTime INTEGER
This is the minimum time an application instance can be idle without Passenger shutting it down. The default value was 300 which means if my app received no traffic for 300 seconds, it could shut down all of my app instances. The result? A visitor would have to wait way too long when viewing my website. I triple starred this because I think this setting alone will greatly improve your app speed. Note there is an obvious memory trade-off because your application instances will always be running.
PassengerMaxRequests INTEGER
This provides a safety net for memory leaks. It tells Passenger to restart an application instance after it receives a certain number of requests. My app is young so I am keeping it at 1000 requests but ideally you should set this to zero meaning no maximum.
RailsAutoDetect ON/OFF
Turn off auto-detection and tell Passenger exactly which directory contains your Rails app. Do this by adding the following line to your VirtualHost configuration block:
<VirtualHost> ... RailsBaseURI / ... </VirtualHost>
RailsAppSpawnerIdleTime INTEGER
This is a similar setting to PassengerPoolIdleTime but applied to the ApplicationSpawner server. If the ApplicationSpawner server hasn’t done anything for the specified amount of time, it will automatically shut down. I set this at zero so it will never shut down and therefore take 10% of the time to spawn a Rails process as it would with the ApplicationSpawner server shut down. I would imagine this becomes increasingly important as your PassengerMaxPoolSize increases. Note that if your application is at it’s maximum number of instances allocated (PassengerMaxPoolSize), you may want the Spawner to shut down immediately after it spawns an app instance since the Spawner won’t be used much. Set the value to 1 if this is the case. I will probably do this in the future when my website has a more constant load ( another option is to write a script to periodically hit your Rails app and keep it at a constant load ).
PassengerStatThrottleRate INTEGER
Tell Passenger to only check for restart.txt up to once every 5 seconds instead of once per processed request.
Finally, try to turn on PassengerHighPerformance:
<VirtualHost> ... PassengerHighPerformance on ... </VirtualHost>
Adding that line to your VirtualHost configuration block will improve your performance but make your Rails app incompatible with some Apache modules. If you turn that on, restart apache, and your Rails app works fine, chances are you are in the clear. Just keep this in mind for the future in case you add more Apache modules.
If you enjoyed this post, make sure you subscribe to my RSS feed!










6 Comments
Hi Tony,
Great post!
I have a question, I’m also using slicehost with a 256 slice.
I’m using passeger and enterprise ruby to deliver a spree shopping Website. The initial launch is slow as heck but the subsequent ones are good.
The first question is my httpd.conf is empty I added the lines there but I didn’t notice on another forum that Ubuntu usually uses apache2.conf should I add the lines there instead?
The apache2.conf is referencing the http.conf so I assume it should include what’s in there. As a side note on it though do I need to include the code in any identifiers or brackets or anything?
Assuming that all is running as it should be, if I need to run a script to keep the app up and running to increase load times could this been done as a cron job? How would I go about doing this? any thoughts or tips?
Again thanks for a great tutorial!!!
d
I can’t accurately tell you how to figure out which conf files your apache installation uses without poking around on your server. If you want to do a quick test, just change something in the conf file, restart apache, and see if those changes took place.
Do you mean the global settings? Like RailsSpawnMethod? No.
Why would you want to write a script to increase load times? If you want to check if your site is up, sure you could write a cron job to ping your site and check for a 500.
Glad you liked the post!
Thanks for the reply!
Everything’s working fine it just takes forever to load on the first hit. If I hit it with firefox first it takes about 1-2 minutes to load. Each subsequent page will load in a few seconds. Also if I use Safari or my phone to hit the site in that time frame it loads fast as well. It’s just always that first initial hit.
I’m doing this for a client and if I have to show him those slow load times I think it’s game over for me.
The script wasn’t to increase load times but rather to make sure the server had a cached copy ready to go.
If you want to hit the site and see it’s at: http://www.eastcoastcarvers.com there’s nothing there right now as I’m waiting for the final images still from his graphic designer and an initial payment to start loading it up with his items.
The first hit is forever the rest are quick. I also don’t SSL setup yet. I’m waiting to get the first payment before I go through that.
Thanks again for the post and the quick reply!
If only all Ruby on Rails help was this quick!
d
Hey d,
Given the general nature of your issue, I can’t really help debug it without poking around on your server and right now I don’t have the resources to offer any free help. Feel free to post any specific questions you have, or maybe someone else will see this comment and be able to help you out.
Best,
Tony
Thanks for the help already!
I’m gonna post over at railsforum and see if anyone can help there.
I appreciate the article and the replies!
d
Thanks for the post! This really helped me get my rails app up and running on my VP slice quite nicely!