we have recently updated an application to Rails 3.0.4 (3.0.5 on online devel server). Most of the changes from 2.3.10 to 3.0.4 were due to obsolete or outdated plugins and gems, and were solvable with relative ease. But one thing makes me go mad:
Every single web request, in development mode, causes the server process to allocate about 50-60 MB more memory than before. This memory is not freed after the request, at least not all of it. After 10-20 requests, every Ruby instance consumed over 500 MB of RAM, while our previous Rails 2.3.10 instances were rarely above 200 MB.
This makes it impossible to run our 1300 tests, because the devel machine's 4GB of RAM is filled before the end of the tests. It only happens in development mode with cache_classes = false
. If I switch cache_classes to true, the Rails instances will consume about 200MB of memory, and then stay there. However, during tests, even with cache_classes = true, memory usage will grow.
I queried ObjectSpace and found out that with each request, about 3500 new Proc, up to 50'000 new Strings and 3000 new Hashes and Arrays are created and not freed. These strings (when dumped) contained my whole source code including plugins and gems, documentation, source code comments and path names. (Why?)
To find the cause for this, here's what I tried: (After every change, I hammered the apps with ab -n 50
.)
pg, rails, aasm, will_paginate, geokit-rails3, koala, omniauth, paperclip
. No change.include
in environment.rb. I also synced boot.rb, environment.rb and application.rb with my bare-bones Rails 3 app, except for five relatively simple observers, autoloading files in /lib and filter_parameters. No change. Every new request still consumed an additional 10-50 MB of RAM.If you have an idea what is going wrong here, and where the memory leak could be, I would really appreciate any help. I am running Rails 3.0.4 on OS X Snow Leopard, Rails 3.0.5 on Debian Lenny, and
Thank you!
I have removed every plugin, every gem, every extension and everything that I did not personally write myself, so that my application is basically naked. Especially, I removed these plugins: acts_as_list, acts_as_tree, asset_packager, forgot_password, fudge_form, fudge_scaffold, paperclippolymorph, query_trace, rails_upgrade, repeated_auto_complete-0.1.0, role_requirement, to_select, validates_url, and ym4r_gm
.
Now my application - only the above FooController still works! - starts up with 65MB and never goes beyond 75MB of RAM, even after hammering it with ab -n 1000 -c1
(1000 HTTP requests to /foo using ApacheBench). Unfortunately, without the plugins, this is also the only URI that works at all.
After some digging, it seems that a combination between the Restful Authentication and Acts As State Machine (AASM) plugins causes the memory leak. See also https://github.com/Satish/restful-authentication/issues#issue/11. I'm not sure yet why, and just doing "include AASM" in my bare-bones project does not cause RAM usage growth just by itself.
I will investigate further.
It is AASM. In Rails 3 it seems to leak AASM::xxx object instances. see
There was another memory leak in rspec. This made my tests almost unbearably slow, even after removing AASM, because two parallel running rspec tasks (using https://github.com/grosser/parallel_tests) took almost 3GB of memory at the end. See https://github.com/rspec/rspec-core/issues/#issue/321.
Some good resources to help you track down the source of the leaks:
Newer:
Find memory leak in a Ruby on Rails project
Older:
ruby/ruby on rails memory leak detection
http://tomcopeland.blogs.com/juniordeveloper/2007/09/tracking-down-a.html
http://xdotcommer.wordpress.com/2009/03/03/tracking-down-a-memory-leak-performance-issues-in-rails/