バンドラーを使用した Rails 2.3.10 アプリがあります。起動時のメモリ フットプリントは非常に大きくなります (開発モードでは 300MB)。
各 gem が起動時にどれだけのメモリを消費するかを確認したいと思います。
バンドラーを使用した Rails 2.3.10 アプリがあります。起動時のメモリ フットプリントは非常に大きくなります (開発モードでは 300MB)。
各 gem が起動時にどれだけのメモリを消費するかを確認したいと思います。
トラフィックやリクエストのない基本的な Rails アプリが、起動時に最大 140MB のフットプリントを持つという問題がありました。
次のアプローチを使用して、バンドラーにパッチを適用することなく、アプリの Gemfile で指定された各 gem のメモリ要件を追跡しました。
rails new myappname
新しい空のレールアプリを生成するbundle install
してrails server
から、Rails サーバーを起動できること、および必要な基本構成がロードされていることを確認します。require: false
の末尾に追加します。1 つの名前で指定されているが :require => 'othergemname' を使用して必要な他の gem が古いルビー ハッシュ表記を使用していることを確認して、以下のパターン マッチがそれをキャッチできるようにします。bundle install
して、Gemfile.lock を再生成します。次のスクリプトを作成します。このスクリプトは、Gemfile で指定された各 gem を手動で require し、前後に rails プロセスによって消費されるシステム メモリをログに記録します。
# require_and_profile.rb
def require_and_profile(gemname = nil)
unless gemname
puts "%-20s: %10s | %10s" % ['gem','increment','total']
return
end
# This is how to get memory of calling process in OS X, check host OS for variants
memory_usage = `ps -o rss= -p #{Process.pid}`.to_i / 1024.0
require gemname
puts "%-20s: %10.2f | %10.2f" % [ gemname, (`ps -o rss= -p #{Process.pid}`.to_i / 1024.0 - memory_usage), (`ps -o rss= -p #{Process.pid}`.to_i / 1024.0)]
end
pattern = /^[^#]*gem[ ]*['"]([^,'"]*)['"][ ,~>0-9\.'"]*(:require[ => ]*['"]([^'"]*)['"][, ])?/
require_and_profile
File.open('Gemfile').each do |line|
if line.match(pattern)
if line.match(pattern)[3]
require_and_profile line.match(pattern)[3]
else
require_and_profile line.match(pattern)[1]
end
end
end
走るrails c
load 'require_and_profile.rb'
これは、たとえば、:asset グループでのみ必要な場合に、ブートでアセット同期を必要としていたことを特定するのに役立ちました。異なるブートアップでは、各 gem のメモリ フットプリントがまったく同じではないことがわかりますが、それを数回実行すると、どれがメモリを消費する gem であるかのパターンが示されます。
私は次のようにします:
c = 0; ObjectSpace.each_object { c += 1 }
)このようにして、どの gem が最も多くのオブジェクトのインスタンス化を引き起こし、したがって間接的に最も多くのメモリ使用量を引き起こしているかがわかります。
ただし、2 つの注意事項があります。