ROR very slow in development while production works fine - ruby-on-rails

I have one rubyonrails app that turned really slow in development mode. Everything is fine in production, but even a simple "hello world" takes seconds in dev. I checked the session store and every possible reason i found on the net, but I didn't find the problem. Am I missing something that is common knowledge? "Completed in 1657ms (View: 226, DB: 39)"

Development is definitely slower, because it reloads all components. Production mode only loads the components when the server is started.
If you find your app is still too slow in Production mode then you can start hunting down bottlenecks. You can start by optimizing DB queries, with :include and indicies. You can also try removing your gems and plugins systematically to find the parts that are slowing down your code.

This is usually the case if you are running webrick, its so slow it makes eyes bleed.
Try installing mongrel in dev
gem install mongrel

Create a new app, see if that's slow too - that'll point to your server stack (apache, mongrel, passenger, etc.) rather than your application. If it's just your application then google rails profiling - and pick one of the many options for profiling an application.

WEBrick is doing a reverse DNS lookup on connecting IPs by default. In other words, it's trying to see if your IP address is associated with a domain name. This is unnecessary and takes too long, so you can disable it.
Open the file "l/ruby/lib/ruby/1.9.1/webrick/config.rb" and locate the line with ":DoNotReverseLookup => nil".
Change nil to true.
Enjoy!

Related

Why would I want to use unicorn or thin instead of WEBrick for development purposes?

I've recently found that some people prefer using unicorn_rails instead of the default WEBrick as a web server for developing Rails applications.
I understand that if I wanted to use unicorn in production, it could make kind of sense to try it out in development, but since the configuration is different in production, is it even relevant?
Is there any real, tangible advantage that I would get from using thin or unicorn instead of WEBrick for developing a Rails application, such as speed or some additional features? Or is this just a matter of personal preference?
It is important to develop as closely as possible to the production environment. It helps ensure that an application will work as expected when deployed into production, instead of stumbling upon bugs at runtime.
This issue is alleviated with the use of Continuous Testing on a Build server that replicates the production environment. Even though you are not actively developing on an identical environment, the Continuous Testing gives you coverage that the application is functioning in the expected way.
As to speed, the performance hit running a Rails app in development mode will negate any benefit the various web servers brings.
In addition to the other answers giving a pretty good overview already, there is also a technical reason you might want to consider using unicorn over WEBrick:
WEBrick does not support subdomains. Support for HTTPS is rather hacky to implement.
So if you have an SaaS application using subdomains, or if you simply want to have admin/api/... subdomain, then WEBrick is not an option. There is POW for Mac OS X, but this won't work for Linux developers.
My personal experience is that Unicorn is much much faster then WEBrick when using a remote machine (ubuntu, 4 cores, 8G mem, connecting though VPN -> ssh) as your development environment (as I do) -- I see sub-1 second page load times with Unicorn, while WEBrick takes 3 to 5 second or more. I'm not sure why, it may have more to do with my network then anything else, but that is what I personally see.
I haven't used Thin for development, as I've read that it requires an additional gem to allow for class reloading in development mode (I can't personally validate the accuracy of that). Also, I am more familiar with Unicorn and use it in production.
My personal experience is that WEBrick is faster in my development environment than Unicorn and Thin (OS X) in a pretty big Rails app (lots of gems, routes etc). But you should measure it yourself, with your app in your machine to see (I tested using ab and using Chrome's developer tools).
However using the same server in production and development is a very good idea.

rails app fast on server, but slow when accessed from another machine

I have a Rails app hosted on a server machine (running Webrick). When I log onto this machine and access the app (via localhost:3000), the app runs smoothly. But when I try to access the app from another machine (via hostname:3000), the app runs super slowly.
I'm not sure how to go about debugging the problem; is there any reason why this would be the case? I also have things like a SQL server database hosted on the same server machine, and accessing the database from other machines works fine.
Updating to add: the server machine, and the other machines I try to access it from, are all on a corporate intranet.
The following answer worked for me. Note that if you are running rvm the answer is at the bottom.
Webrick is very slow to respond. How to speed it up?
Look for the file /usr/lib/ruby/1.9.1/webrick/config.rb and edit it.
Replace the line
:DoNotReverseLookup => nil,
with
:DoNotReverseLookup => true,
rvm file is ~/.rvm/rubies/ruby-your-version/lib/ruby/your-version/webrick/config.rb
The most obvious answer would be that the problem is not with rails, but with your Domain Hosting(i.e. your DNS is super slow).
Try and load a different app(maybe a Sinatra "hello world") and see if it exhibits the same symptoms.
If yes - your domain provider is to blame.
If the problem persists, increase the verbosity of the logs and check if any SQL queries are an obvious bottleneck.
Also, the problem may be with Webrick. It just wasn't meant for production and may be slow if several people use the app at once. Try it with a different server. Apache is a reasonable choice: http://www.modrails.com/
I'm late to the party but you can use Thin instead of Webrick.
just add to Gemfile
gem 'thin'
Webrick isn't the fastest in the world, I'm fairly positive it's not meant for production but rather local testing. When you're connecting to the other machine is it on a local network or over the internet?
Take a look at the response times listed in your rails log file. If they are the same for local and remote access, then you know your problem is somewhere else in the stack (DNS, routing, software firewall, etc.)
It's highly likely that the problem is not rails itself.

Is it correct that there are particular times when you may need to restart Webrick to see your changes?

I heard Kevin Skoglund (lynda.com) say that it is good practice to get in the habit of restarting Webrick frequently during development. Although generally you do not need to restart Webrick to see your changes, he implied that there are particular times when this may be needed? Does anyone know what those circumstances might be? This made wonder if Webrick is kind of flaky.
If you are working through the Lynda.com tutorials, then you are working with a much earlier version of Rails then the most recent release (2.3.2).
The short answer is, large amounts of restarts are no longer necessary when working in the development environment. I think Kevin has you restart the server every time you change a Model object, but that isn't the case anymore.
The general rule of thumb is: restart every time you change something in the config or lib folder . . . any other code changes shouldn't necessitate a restart. It is also a good idea to restart when you change your routes.rb file as well, although when working with it today I noticed it is not a hard and fast rule.
The reason for all of the server restarts isn't necessarily because your webserver (webrick, mongrel, phusion passenger) is flaky, but because when your Rails app has started up, there are certain things loaded into memory, load paths, initializers, environment data. When you make a change to one of these files, you want to restart your application so that the changes take place (as opposed to the old stuff that is still running in memory)
You'll need to restart if you change your database schema, or if you add/change a constant.
I think Rails uses Mongrel by default for development now, but those still apply.

Mongrel hangs after several hours

I'm running into a problem in a Rails application.
After some hours, the application seems to start hanging, and I wasn't able to find where the problem was. There was nothing relevant in the log files, but when I tried to get the url from a browser nothing happened (like mongrel accept the request but wasn't able to respond).
What do you think I can test to understand where the problem is?
I might get voted down for dodging the question, but I recently moved from nginx + mongrel to mod_rails and have been really impressed. Moving to a much simpler setup will undoubtedly save me headaches in the future.
It was a really easy transition, I'd highly recommend it.
Are you sure the problem is caused by Mongrel? Have you tried running your application under WEBrick?
There are a few things you can check, but since you say there's nothing in the logs to indicate error, it sounds like you might be running into a bug when using the log rotation feature of the Logger class. It causes mongrel to lock up. Instead of relying on Logger to rotate your logs, consider using logrotate or some other external log rotation service.
Does this happen at a set number of hours/days every time? How much RAM do you have?
I had this same problem. The couple options I had narrowed it down to were MySQL adapter related. I was running on Red Hat Enterprise Linux 4 (or 5) and the app would hang after a given amount of idle time.
One suggested solution was to compile native MySQL bindings, I had been using the pure Ruby one.
The other was to set the timeout on the MySQL adapter higher than what the connection would idle out on. (I don't have the specific configuration recorded, but as I recall it was in environment.rb and it was some class variable in the mysql adapter.)
I don't recall if either of those solutions fixed it, we moved to Ubuntu shortly after that and hadn't had a problem since.
Check the Mongrel FAQ:
http://mongrel.rubyforge.org/wiki/FAQ
From my experience, mongrel hangs when:
the log file got too big (hundreds of megabytes in size). you have to setup log rotation.
the MySQL driver times out
you have to change the timeout settings of your MySQL driver by adding this to your environment.rb:
ActiveRecord::Base.verification_timeout = 14400
(this is further explained in the deployment section of the FAQ)
Unfortunately, Rails (and thereby Mongrel) using up too much memory over time and crashing is a known problem (50K+ Google entries for "Ruby, rails, crashing, memory"). The current ruby interpreter has the property that it sometimes simply fails entirely to give memory back to the system - it may reuse the memory it has but it won't give it up.
There are numerous schemes for monitoring, killing and restarting Mongrel instances in a production environment - for example: (choosing at random) rails monitor . Until the problem is fixed more decisively, one of these may be your best bet.
We have experienced this same issue. First off, install the mongrel_proctitle gem
http://github.com/rtomayko/mongrel_proctitle/tree/master
This gem/plugin will allow you to view the mongrel processes via "ps" and you can see if a Mongrel is hung. An issue we have seen with Mongrel is that it will happily accept connections and enqueue them, then wedge itself. This plugin will help you see when a Mongrel has been wedged but then you must use another monitoring app to actually restart a a wedged Mongrel, something like Monit or God
You might also want to consider putting a more balanced reverse proxy in front of your Mongrels, something HAproxy, instead of nginx, Apache or Lighttpd. With a setting of "maxconn 1" in HAproxy you can assure that the queue is being maintained by HAproxy versus Mongrel. The other reverse proxies (nginx, Apache, Lighttpd) only do round-robin which means that they can load up your Mongrel queue, inadvertently.
My personal choice is God as it is much more flexible.
tl;dr Install this gem plugin and keep an eye on your Mongrels. Try Apache+Phusion Passenger.

How can I find out why my app is slow?

I have a simple Rails app deployed on a 500 MB Slicehost VPN. I'm the only one who uses the app. When I run it on my laptop, it's fast enough. But the deployed version is insanely slow. It take 6 to 10 seconds to load the login screen.
I would like to find out why it's so slow. Is it my code? (Don't think so because it's much faster locally, but maybe.) Is it Slicehost's server being overloaded? Is it the Internet?
Can someone suggest a technique or set of steps I can take to help narrow down the cause of this problem?
Update:
Sorry forgot to mention. I'm running it under CentOS 5 using Phusion Passenger (AKA mod_rails or mod_rack).
If it is just slow on the first time you load it is probably because of passenger killing the process due to inactivity. I don't remember all the details but I do recall reading people who used cron jobs to keep at least one process alive to avoid this lag that can occur with passenger needed to reload the environment.
Edit: more details here
Specifically - pool idle time defaults to 2 minutes which means after two minutes of idling passenger would have to reload the environment to serve the next request.
First, find out if there's a particularly slow response from the server. Use Firefox and the Firebug plugin to see how long each component (including JavaScript and graphics) takes to download. Assuming the main page itself is what is taking all the time, you can start profiling the application. You'll need to find a good profiler, and as I don't actually work in Ruby on Rails, I can't suggest any: google "profile ruby on rails" for some options.
As YenTheFirst points out, the server software and config you're using may contribute to a slowdown, but A) slicehost doesn't choose that, you do, as Slicehost just provides very raw server "slices" that you can treat as dedicated machines. B) you're unlikely to see a script that runs instantly suddenly take 6 seconds just because it's running as CGI. Something else must be going on. Check how much RAM you're using: have you gone into swap? Is the login slow only the first time it's hit indicating some startup issue, or is it always that slow? Is static content served slow? That'd tend to mean some network issue (either on the Slicehost side, or your local network) is slowing things down, assuming you're not in swap.
When you say "fast enough" you're being vague: does the laptop version take 1 second to the Slicehost 6? That wouldn't be entirely surprising, if the laptop is decent: after all, the reason slices are cheap is because they're a fraction of a full server. You're using probably 1/32 of an 8 core machine at Slicehost, as opposed to both cores of a modern laptop. The Slicehost cores are quick, but your laptop could be a screamer compared to 1/4 of core. :)
Try to pint point where the slowness lies
1/ application is slow, or infrastructure (network + web server)
put a static file on your web server, and access it through your browser
2/ If it is fast, it is probable a problem with application + server configuration.
database access is slow
try a page with a simpel loop: is it slow?
3/ If it slow, it is probably your infrastructure. You can check:
bad network connection: do a packet capture (with Wireshark for example) and look for retransmissions, duplicate packets, etc.
DNS resolution is slow?
server is misconfigured?
etc.
What is Slicehost using to serve it?
Fast options are things like: Mongrel, or apache's mod_rails (also called passenger phusion or
something like that)
These are dedicated servers (or plugins to servers) which run an instance of your rails app.
If your host isn't using that, then it's probably defaulting to CGI. Rails comes with a simple CGI script that will serve the page, but it reloads the app for every page.
(edit: I suspect that this is the most likely case, that your app is running off of the CGI in /webapp_directory/public/dispatch.cgi, which would explain the slowness. This tends to be a default deployment on many hosts, since it doesn't require extra configuration on their part, but it doesn't give good performance)
If your host supports "Fast CGI", rails supports that too. Fast CGI will open a CGI session, and keep it open for multiple pages, so you get much better performance, but it's not nearly as good as Mongrel or mod_rails.
Secondly, is it in 'production' or 'development' mode? The easy way to tell is to go to a page in your app that gives an error. If it shows you a stack trace, it's in development mode, which is slower than production mode. Mongrel and mod_rails have startup options to determine whether to run the app in production or development mode.
Finally, if your database is slow for whatever reason, that will be a big bottleneck as well. If you do have a good deployment (Mongrel/mod_rails/etc.) in production mode, try looking into that.
Do you have a lot of data in your DB? I would double check that you have indexed all the appropriate columns- because this can make a huge difference. On your local dev system, you probably have a lot more memory than on your 500 mb slice, which would result in the DB running a lot slower if you have big, un indexed tables. You can also run the slow queries logger in MySql to pinpoint columns without indexes.
Other than that, yes- passenger will need to spool up a process for you if you have not been using the site recently. If this is the case, you should see a significant speed increase on second, and especially third and later page loads.
You might want to run a local virtual machine with 500 MB. Are you doing a lot of client-server interaction? Delays over the WAN are significant
You might want to check out RPM (there's a free "lite" version too) and/or New Relic's Tune Up.
Your CPU time is guaranteed by Slicehost using the Xen virtualization system, so it's not that. Don't have the other answers for you, sorry! Might try 'top' on a console while you're trying to access the page.
If you are using FireFox and doing localhost testing (or maybe even on LAN) you may want to try editing the network.dns.disableIPv6 setting.
Type about:config in the address bar and filter for network.dns.disableIPv6 and double-click to set to true.
This bug has been reported mainly from Vista OS's, but some others as well.
You could try running 'top' when you SSH in to see which process is heavy. If you also have problems logging you, perhaps you may try getting Statistics in the Slicehost manager.
If you discover it is MySQL's fault, consider decreasing the number of servers it can spawn.
512 seems decent for Rails application, you might have to check if you misconfigured too.

Resources