ruby-on-rails-3 - 在 Ruby on Rails 3/Postgres/Apache Passenger 应用程序中跟踪内存泄漏

标签 ruby-on-rails-3 postgresql memory-leaks rspec-rails

你好,

我们最近将一个应用程序更新到 Rails 3.0.4(在线开发服务器上的 3.0.5)。从 2.3.10 到 3.0.4 的大部分更改是由于过时或过时的插件和 gem,并且相对容易解决。但有一件事让我发疯:

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

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

我查询了 ObjectSpace,发现每个请求都会创建大约 3500 个新 Proc、多达 50'000 个新字符串和 3000 个新哈希和数组,但没有被释放。这些字符串(转储时)包含我的整个源代码,包括插件和 gem、文档、源代码注释和路径名。 (为什么?)

为了找到原因,这是我尝试过的:(每次更改后,我都用 ab -n 50 敲打应用程序。)

  • 我创建了一个 新鲜的 Rails 3 应用 使用单个资源和 Controller 以及 SQLite3 DB。内存使用量从 60 MB 开始,一直低于 80 MB。
  • 我改了 “sqlite3”到“pg”并将新的 Rails 3 应用程序指向我现有的 Postgres DB。内存使用量从 110 MB 开始,并没有超过 130 MB。 (附带问题:为什么 Postgres gem 使用的内存比 SQLite3 gem 多这么多?)
  • 我复制了我的 Gemfile 和 Gemfile.lock 从损坏的 Rails3 应用程序到裸机应用程序并运行捆绑安装。没有变化,无论发出多少请求,内存都保持在 115MB 左右。
  • 我在损坏的 Rails3 应用程序中创建了一个空的“def FooController; def foo; render :text => 'foo' end; end”。内存使用量增长更慢,但在请求之后它仍然没有停止增长。
  • 我删除了除 FooController 路由之外的所有路由。没变。
  • 我禁用了除以下之外的所有 gem :pg, rails, aasm, will_paginate, geokit-rails3, koala, omniauth, paperclip .没变。
  • 我禁用了 ApplicationController 中的所有 before_filter 和 after_filter 以及所有不必要的 include在 environment.rb 中我还将 boot.rb、environment.rb 和 application.rb 与我的基本 Rails 3 应用程序同步,除了五个相对简单的观察者、/lib 和 filter_parameters 中的自动加载文件。没变。每个新请求仍会额外消耗 10-50 MB 的 RAM。

  • 如果您知道这里出了什么问题,以及内存泄漏可能在哪里,我将非常感谢您的帮助。我在 OS X Snow Leopard 上运行 Rails 3.0.4,在 Debian Lenny 上运行 Rails 3.0.5,以及

    谢谢!

    接近了:

    我已经删除了所有插件,每个 gem,每个扩展以及所有不是我亲自编写的内容,因此我的应用程序基本上是裸露的。特别是,我删除了这些插件: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 对象实例。看
  • https://github.com/jeffp/enumerated_attribute/issues/#issue/20
  • https://github.com/rubyist/aasm/issues/31
  • https://github.com/Satish/restful-authentication/issues/#issue/11

  • 找到第二个罪魁祸首

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

    最佳答案

    关于ruby-on-rails-3 - 在 Ruby on Rails 3/Postgres/Apache Passenger 应用程序中跟踪内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5369623/

    相关文章:

    mysql - Rails 3 和 ActiveRecord - 关于日期的 sql 查询

    ruby-on-rails-3 - 使用rspec在Rails中 stub 保存方法

    node.js - Express JS 对查询结果返回 null,并在使用 pgAdmin 查询时显示值

    ruby-on-rails - 错误-heroku "insecure world writable dir/var/psql_socket in PATH"

    c pthreads + valgrind = 内存泄漏 : why?

    ruby-on-rails - Rails Devise - 多种用户模型,一次登录

    ruby-on-rails - rails 3 : What is the difference between an Engine and a Gem?

    sql - 如何查询UNION查询的结果

    快速组合接收器接收值内存泄漏

    .net - "ContentPresenter.Content"内存泄漏