I'm writing a web application to monitor a furniture factory production flow. It has thousand of data to handle. So far, I run RoR on Mongrel + MySQL and it's really really slow (2-4min for some views). When I look at RoR logs, it seems that database queries aren't slow (0-10ms).
Is RoR slow when it converts database data to object ? Is Mongrel slow ?
Edit: First thing: I was in dev. env. In production environment, the slowest view takes 2min (which would turn down to less than 1min on a good computer, mine is 5 years old). With ruby-prof and a bit of common sense, I've found out which methods were slowing down the application. The problem is that single sql queries are called in loops on larges datasets:
ofs = Ofkb.find_by_sql ["..some large sql query..."]
for of in ofs # About 700-1000 elements
ops = Operation.find(..the single query..)
etc.
end
Here are ruby-prof results on those methods:
%self total self wait child calls name
32.19 97.91 97.91 0.00 0.00 55 IO#gets (ruby_runtime:0}
28.31 86.39 86.08 0.00 0.32 32128 Mysql#query (ruby_runtime:0}
6.14 18.66 18.66 0.00 0.00 12432 IO#write (ruby_runtime:0}
0.80 2.53 2.42 0.00 0.11 32122 Mysql::Result#each_hash (ruby_runtime:0}
Problem is: I can't really avoid those single queries. I've got thousand of events from which I have to compute complex data. Right now I'm using memcached on those methods which is OK unless your the first to request the page.
You might profile the code first before doing anything, though, queries inside for loops are a very common cause for performance problems and at first sight this seems your problem. You might anyway find a practical profiler here:
As already said on the other answers, if both models are related you should eager load the associations, which implies instructing Active Record to perform join queries:
If you do not need the ofkbs but only the operations, you could perform an inner join
This solution only preforms one query, and allows you to afterwards iterate through the data that will have already been collected from the DB:
If the queries are very complicated you should use arel instead.
I'll agree with everyone else. You have to profile. There is no point in doing anything to your code until you know what specifically is causing the slowness. Trying to fixing a problem without understanding the cause is like feeling ill and deciding to have lots of surgery until you feel better. Diagnose your problem first. It might be something small like a network setting or it could be one bad line in your code.
Some tips for profiling:
How to Profile Your Rails Application
Performance Testing Rails Applications
At the Forge - Profiling Rails Applications
Once you have found the bottleneck you can figure out what to do.
I recommend these videos: Railslab Scaling Rails
Revised now based on prof results:
OK. Now that you can see that your problem is that you are doing some sort of calculation using a query based on looping through the results of another active record query I'd advise you to look into building a custom SQL statement combining your initial selection criteria and the loop calculation to get what you need. You can definitely speed this up by optimizing the SQL.
There are some good screen casts on this topic http://railslab.newrelic.com/scaling-rails
Things like fragmet caching and using :include (to avoid n+1) can help. It sounds like you're already using memcached, so why not curl the url to prefetch the cache?
Execution times this long would make me suspect a network issue - maybe a DNS query is timing out on a primary DNS server?
When I bound the server to the boxes ip address instead of 0.0.0.0, this sped things up for me.