跟踪Ruby on Rails 3/Postgres/Apache Passenger应用程序中的内存泄漏

Jen*_*ens 15 postgresql memory-leaks rspec-rails ruby-on-rails-3

你好,

我们最近更新了一个应用程序到Rails 3.0.4(在线开发服务器上的3.0.5).从2.3.10到3.0.4的大多数变化都是由于过时或过时的插件和宝石,并且相对容易解决.但有一件事让我发疯:

在开发模式下,每个Web请求都会导致服务器进程分配比以前 50-60 MB的内存.请求后释放此内存,至少不是全部内存.在10-20个请求之后,每个Ruby实例消耗超过500 MB的RAM,而我们以前的Rails 2.3.10实例很少超过200 MB.

这使得无法运行我们的1300次测试,因为在测试结束之前,开发了4GB的RAM.它只发生在开发模式中cache_classes = false.如果我将cache_classes切换为true,Rails实例将消耗大约200MB的内存,然后保留在那里.但是,在测试期间,即使cache_classes = true,内存使用量也会增加.

我查询了ObjectSpace并发现每次请求时,大约有3500个新的Proc,最多50'000个新的Strings和3000个新的Hashes和Arrays被创建并且没有被释放.这些字符串(转储时)包含我的整个源代码,包括插件和gem,文档,源代码注释和路径名.(为什么?)

为了找到原因,这是我尝试过的:(每次更改后,我都会使用ab -n 50.)

  1. 我用一个资源和控制器以及SQLite3 DB 创建了一个全新的Rails 3应用程序.内存使用量从60 MB开始,并保持在80 MB以下.
  2. 我将'sqlite3'更改为'pg'并将新的Rails 3应用程序指向我现有的Postgres DB.内存使用量从110 MB开始,并没有超过130MB.(旁边的问题:为什么Postgres gem使用比SQLite3 gem更多的内存?)
  3. 我将我的Gemfile和Gemfile.lock从破碎的Rails3应用程序复制到裸骨应用程序并运行bundle install.没有变化,无论提出多少请求,内存都保持在115MB左右.
  4. 我在破碎的Rails3应用程序中创建了一个空的"def FooController; def foo; render:text =>'foo'end; end".内存使用量增长缓慢,但在请求后仍然没有停止增长.
  5. 我删除了除FooController路由之外的所有路由.没有变化.
  6. 我禁用了所有Gems,除了以下内容:pg, rails, aasm, will_paginate, geokit-rails3, koala, omniauth, paperclip.没有变化.
  7. 我在ApplicationController中禁用了每个before_filter和after_filter,在environment.rb中禁用了每个不必要include的东西.我还使用我的简单Rails 3应用程序同步了boot.rb,environment.rb和application.rb,除了五个相对简单的观察者,在/ lib和filter_parameters中自动加载文件.没有变化.每个新请求仍然消耗额外的10-50 MB RAM.

如果你知道这里出了什么问题,以及内存泄漏的地方,我真的很感激任何帮助.我在OS X Snow Leopard上运行Rails 3.0.4,在Debian Lenny上运行Rails 3.0.5,以及

谢谢!

接近了:

我已经删除了每个插件,每个宝石,每个扩展以及我自己亲自编写的所有内容,因此我的应用程序基本上是裸露的.特别是,我删除了这些插件: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.

现在我的应用程序 - 只有上面的FooController仍然有效!- 以65MB的速度启动,永远不会超过75MB的RAM,即使用锤击它ab -n 1000 -c1(使用ApacheBench向/ foo发送1000个HTTP请求)也是如此.不幸的是,没有插件,这也是唯一可以工作的URI.

经过一些挖掘,似乎Restful Authentication和Acts As State Machine(AASM)插件之间的组合会导致内存泄漏.另见https://github.com/Satish/restful-authentication/issues#issue/11.我不确定为什么,只是在我的裸机项目中"包含AASM"并不会导致RAM使用量的增长.

我会进一步调查.

罪魁祸首找到了

这是AASM.在Rails 3中,它似乎泄漏了AASM :: xxx对象实例.看到

发现了第二个罪魁祸首

rspec中还有另一个内存泄漏.这使得我的测试几乎无法忍受,即使在删除AASM之后,因为两个并行运行的rspec任务(使用https://github.com/grosser/parallel_tests)最后占用了近3GB的内存.请参阅https://github.com/rspec/rspec-core/issues/#issue/321.