Ruby on Rails 3 / Postgres / Apache Passengerアプリケーションのトレースメモリリーク
-
27-10-2019 - |
質問
こんにちは、
最近、Rails 3.0.4(オンラインDevel Serverで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を超えることはめったにありませんでした。
これにより、Devel Machineの4GBのRAMがテストの終了前に満たされているため、1300のテストを実行することができません。開発モードでのみ発生します cache_classes = false
. 。 cache_classesをtrueに切り替えると、Railsインスタンスは約200 mbのメモリを消費し、そこにとどまります。ただし、テスト中、cache_classes = trueであっても、メモリの使用量が増加します。
私はObjectSpaceを照会しましたが、各リクエストでは、約3500個の新しいProc、最大50'000個の新しいストリングと3000個の新しいハッシュとアレイが作成され、解放されていないことがわかりました。これらの文字列(ダンプされたとき)には、プラグインと宝石、ドキュメント、ソースコードのコメント、パス名を含む私のソースコード全体が含まれていました。 (どうして?)
これの原因を見つけるために、私が試したものがここにあります:(すべての変更の後、私はアプリをハンマーしました ab -n 50
.)
- 私は作成しました フレッシュレール3アプリケーション 単一のリソースとコントローラーとSQLite3 dBを使用。 メモリの使用量は60 MBで始まり、80 MB以下のままでした.
- 私が変更され 「sqlite3」から「pg」 新しいRails 3アプリを既存のPostgres DBに向けました。 メモリ使用量は110 MBで始まり、130MBを超えて成長しませんでした. 。 (サイド質問:なぜPostgres GemはSQLite3 GEMよりもはるかに多くのメモリを使用するのですか?)
- 私は自分の上にコピーしました Gemfile and Gemfile.Lock 壊れたRails3アプリからBare Bonesアプリまで バンドルインストール. 変化なし, 、記憶は、いくつのリクエストが行われても、約115MBにとどまりました。
- 壊れたRails3アプリに空の「def foocontroller; def foo; render:> 'foo' end; end」を作成しました。 メモリの使用量はよりゆっくりと成長しましたが、リクエスト後も成長することはありませんでした.
- Foocontrollerルートを除くすべてのルートを削除しました。 変化なし.
- 以下を除いて、すべての宝石を無効にしました。
pg, rails, aasm, will_paginate, geokit-rails3, koala, omniauth, paperclip
. 変化なし. - ApplicationControllerおよびすべての非必須であるすべてのbefore_filterとafter_filterを無効にしました
include
In Environment.RB。また、5つの比較的単純なオブザーバー、 /libおよびfilter_parametersのオートロードファイルを除き、Bare-bones Rails 3アプリを使用して、boot.rb、environment.rb、application.rbを同期しました。 変化なし. 。すべての新しいリクエストは、さらに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認証とState Machine(AASM)プラグインとして機能すると、メモリリークが発生するように思われます。参照してください https://github.com/satish/restful-authentication/issues#issue/11. 。私はまだ理由がわからないので、私の裸のボーンズプロジェクトで「Asmを含める」ことをするだけでは、それ自体だけでRAMの使用の成長を引き起こすことはありません。
さらに調査します。
犯人が見つかりました
それはASMです。 Rails 3では、ASM :: 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
2番目の犯人が見つかりました
RSPECには別のメモリリークがありました。これにより、2つの並列実行されているRSPECタスク(使用)を使用するため、テストはASMを削除した後でも、ほとんど耐えられないほど遅くなりました。 https://github.com/grosser/parallel_tests)最後にほぼ3GBのメモリを取りました。見る https://github.com/rspec/rspec-core/issues/#issue/321.