views:

68

answers:

2

I am getting bad performance after upgrading an application to Rails 3.

Before upgrading, I got 60ms - 100ms response times.

After upgrading, I get 300ms - 1500ms response times.

The log shows a sample response time from each time:

Rails 3.0.0: Completed 200 OK in 1454ms (Views: 1314.6ms | ActiveRecord: 25.1ms)
Rails 2.3.8: Completed in 31ms (View: 27, DB: 1) | 200 OK [FILTERED]

I've tried running using passenger and 'rails server' (both results are close). I've created two identical applications (running in 2.3.8 and 3.0.0) to demonstrate the performance differences. The code that appears to be causing the performance issues is:

<%- @posts.each do |post| -%>
  <h1><%= post.title %></h1>
  <p><%=truncate post.body %></p>
  <%- post.comments.each do |comment| -%>
    <h2><%= comment.title%></h2>
    <p><%=truncate comment.body %></p>
    <ul>
    <%- comment.ratings.each do |rating| -%>
      <li><%=truncate rating.notes %></li>
    <%- end -%>
    </ul>
  <%- end -%>
<%- end -%>

For full source, the projects are available here: http://github.com/ksylvest/performance

Thanks!

+1  A: 

Without much to go on, there's not much anyone can do.

generated source files

In Ruby?

Really?

nested loops

select n+1? Do you need to specify in certain queries that specific associations need to be eager-loaded?

--EDIT--

The ActiveRecord query API and performance characteristics have changed significantly from v2 to v3.

Perhaps you need to eager-load some associations?

To eager-load the comments with the posts, use

@posts = Post.includes(:comments)

and to eager-load the comments and the comments' ratings with the posts, use

@posts = Post.includes(:comments => :ratings)
Justice
Hi Justice. Sorry it is difficult to be precise, but I am seeing a slow down application wide. The logs show that the ActiveRecord queries are approximately the same, but the view rendering times have gone up by 100 times. I'm just wondering if others have experienced similar issues.
Kevin Sylvestre
@Justice Hi Justice. Sorry I couldn't release any source for the original project, but I spent an hour generating sample projects that appear to have the same issue. The project is dead simple and just features basic nested looping.
Kevin Sylvestre
I added some hints about eager-loading. Do these hints help at all with your projects?
Justice
Hi Justice. Thanks for the update. This cut down the runtime in both sample application I posted; I am currently using some eager loading in the private application, but I will be sure to check through to find any more improvements. However, my larger concern was moving from Rails 2.3.8 to Rails 3.0.0 and the five-ten slow down I experienced. Thanks for the great info though. Do you know if the lazy loading can be defaulted application wide? Thanks again!
Kevin Sylvestre
As an additional note. I pushed up a new version of the code so that others can see the performance improvements when using eager loading. The tests will now do benchmarks that I found useful in troubleshooting a few environment issues. Also, the eager loading seems to have a larger performance improvement (for me) in Rails 3.0.0 than in Rails 2.8.7.
Kevin Sylvestre
You can take a look at the `:has_many` method's `:include` options hash parameter: `Post.send :has_many, :categories, :include => :ratings`.
Justice
@Justice Thanks! I'll take a look through it!
Kevin Sylvestre
+1  A: 

Please include the version of Ruby you are using for your tests.

Try running Rails 3 on Ruby 1.9.2-head and see if you notice a difference. You can use something like RVM to try multiple versions of Ruby very easily.

As noted in this SO question, 1.9.1 seems to have some performance issues. If you are using Ruby Enterprise Edition with Rails 3, that may be causing some performance issues as well. If you use plugins that are not Ruby 1.9 compatible, make sure you are using REE >= 1.8.7-2010.02 as noted on the Edge Rails Guides.

I believe Rails 3 development is being targeted at 1.9.2 and backported to run on earlier versions.

Awgy
Thanks for the advice. ruby --version gives:ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0]I am deploying to Heroku (currently only supports 1.8.7 and 1.9.1) and I am not sure about my plugin compatibility (will need some major time to test). I will check to see if the sample code has any performance changes with different ruby versions.
Kevin Sylvestre
@Kevin Sylvestre: Heroku does support the correct version of REE as noted in their latest blog post: http://blog.heroku.com/archives/2010/6/15/rails_3_beta_4_on_heroku/ You can check which stack you are running by typing `heroku stack`
Awgy
@Awgy Oops! Thanks you are right! I was using this as a guideline: http://docs.heroku.com/rails3. Looks like they have some out-of-date documentation. Thanks, I'll test it shortly.
Kevin Sylvestre
@Awgy I just finished figuring out RVM and running the tests! Using 1.9.2 reduced the response time to 20% of that when using 1.8.7 in the sample application. Now I just need to sort out some dependencies! Thanks for the help! That was exactly what I needed!
Kevin Sylvestre
@Kevin Sylvestre: I'm happy to hear that it helped =)
Awgy
@Awgy Just wondering how you managed to get the stack to 1.9.2 on Heroku? When I type heroku stack it only lists 1.8.6, 1.8.7 and 1.9.1. I read a bit more on the page and they mentioned that support will be available when it is officially released, so I am confused. Thanks.
Kevin Sylvestre
Have you got a benchmark how it improved the performance?
jpartogi
@Kevin Sylvestre: Heroku does not support 1.9.2 yet according to that blog post I linked. I use 1.9.2-head on a Slicehost VPS, which I find works very well price/performance wise compared to Heroku if you are up for the additional administration.
Awgy
@jpartogi You can try to run the benchmarks on your own to see. Just install RVM and download the source linked in the question. I found about four time performance improvements from upgrading Ruby and a two times improvement from adding eager loading.
Kevin Sylvestre
@Kevin: 4 time performance improvements is damn fast. I think I should try it. Thanks.
jpartogi