先に結論
計測してみた
適当な長さのStringを10000回作って、RSSと、ObjectSpace.memsize_of_all
を計測する
require 'objspace' puts ",ObjectSpace.memsize_of_all,RSS" 1.upto(10000) do |i| a = "10"*10000 a += '123' rss = `ps -o rss= -p #{Process.pid}`.to_i * 0.001 memsize_of_all = ObjectSpace.memsize_of_all * 0.001 * 0.001 puts "#{i},#{rss},#{memsize_of_all}" end
結果
以下のグラフの通り
memsize_of_all
は数ループに1回GCされているが、実際にプロセスがメモリを手放すタイミングはもっとゆっくりしている
単位はMB
なんでGCしても、RSSはすぐに減らないの?
stackoverflowだけれど納得感のある解説を見つけた
Cレベルの話をすると、free を呼んでもOSにメモリを返さず、次に malloc した際に再割当するような実装も多く存在します。 ということで、一般的にはメモリの解放によっても占有メモリが減らない前提でプログラミングすることになろうかと思います。
2018/05/18 追記
会社のひとから、上記のコメントは Conservative GC と混同しているのではないか? とご意見頂いた
参考リンク
- ObjectSpace.memsize_of_all
- すべての生存しているオブジェクトが消費しているメモリ使用量をバイト単位 で返します。
- Rubyプロセスの使用メモリ量の計測