長時間実行プロセスの一部として、Logger
出力をフォーマットして現在のメモリ使用量を含めたいと思います。
Ruby、PHPの memory_get_usage()
に少し似ているものに組み込みのものはありますか? ps
から?
1年前にこの問題を解決しようとしたとき、私は多くのオンライン調査とAPIの調査を行いましたが、psへのシステムコールを介してしか解決できませんでした。
OS X 10.7.2とRed Hat 4.1.2-13(EC2上)の両方で:
pid, size = `ps ax -o pid,rss | grep -E "^[[:space:]]*#{$$}"`.strip.split.map(&:to_i)
これにより、プロセスの常駐メモリサイズが取得され、キロバイト単位でサイズ変数に格納されます。
少しの努力でこれをクリーンアップできますが、ほとんどの時間はpsを呼び出してその出力をキャプチャするために費やされるため、時間の価値はないと思います。
NewRelic gemは、多数のオペレーティングシステムとRubyランタイムとその MemorySampler
クラス ]に対する単純なRSS使用の実装を提供します。
newrelic_rpm
gemをGemfile
に含めて呼び出します。
NewRelic::Agent::Samplers::MemorySampler.new.sampler.get_sample
また、現在のプロセスが保持しているメモリのメガバイト数をRSSとして返します。
実装では、利用可能なインプロセスカウンター(jruby)を優先し、Linuxでは/proc/#{$$}/status
を使用し、その他の場所ではps
にフォールバックします。
Rubyでps
などの外部コマンドを使用してバックティックを使用すると、コマンドの実行中に現在のプロセスがフォークされます。これは、Rubyプロセスが300mbを消費する場合、これらの`ps -o rss #{$$}`.strip.split.last.to_i
ソリューションのいずれかを実行するためにさらに300mbが必要になることを意味します。
Linuxベースのシステムでは、/proc/PID/statm
を読み取ることでプロセスメモリ情報を取得できます。 2番目のフィールドは、カーネルページ数の常駐セットサイズです。 RSSページをバイトに変換するには、カーネルページサイズ(ほとんどの場合4096)を把握する必要があります。
Linuxで動作する、rsをキロバイト単位で取得するサンプルコードを次に示します。 OSXや他のシステムでこれを行う方法がわかりません。
module MemInfo
# This uses backticks to figure out the pagesize, but only once
# when loading this module.
# You might want to move this into some kind of initializer
# that is loaded when your app starts and not when autoload
# loads this module.
KERNEL_PAGE_SIZE = `getconf PAGESIZE`.chomp.to_i rescue 4096
STATM_PATH = "/proc/#{Process.pid}/statm"
STATM_FOUND = File.exist?(STATM_PATH)
def self.rss
STATM_FOUND ? (File.read(STATM_PATH).split(' ')[1].to_i * KERNEL_PAGE_SIZE) / 1024 : 0
end
end
# >> MemInfo.rss
# => 251944
OS gemにはrss_bytesメソッドがあります。
このputsステートメントを簡単に使用できます
puts 'RAM USAGE: ' + `pmap #{Process.pid} | tail -1`[10,40].strip