前提
- メモリ使用量と処理時間
- Ruby 2.7.4
メモリ使用量
Gem
- memprof2を使う
- Ruby コードのどの行がどのぐらいメモリ(bytes)を消費しているか調べられる
- かなりリソースを喰うらしい
# 計測前に掃除
GC.start
# 計測開始
Memprof2.start
# 計測対象
12.times{ "abc" }
# 計測後に計測対象をクリア
# gem内部は除いている
Memprof2.report!(ignore: /.*\/gems\/.*/)
# 計測終了
Memprof2.stop
# =>
# 168 tmp/test.rb:9:Hash
# 480 tmp/test.rb:6:String
psコマンド
- Ruby からコマンドを実行する
-
RSSとVSZでメモリ確保のタイミングが異なる
- 前提:
- 1.メモリ確保
- 2.メモリ読み込み
- 3.メモリ書き込み
- VSZ(仮想メモリ)は 1 で増える
- RSS(物理メモリ)は 3 で増える
- 前提:
def puts_ps
# NOTE KB -> MB を行う。詳細は、man ps で確認できる。
rss = `ps -o rss= -p #{Process.pid}`.to_i * 0.001024
vsz = `ps -o vsz= -p #{Process.pid}`.to_i * 0.001024
puts "Process: #{Process.pid}: RSS = #{rss} MB, VSZ = #{vsz} MB"
end
# 計測前に掃除
GC.start
# 計測前
puts_ps
# 計測対象
12.times{ "abc" }
# 計測後
puts_ps
# =>
# Process: 2016: RSS = 210.73600000000002 MB, VSZ = 6550.928 MB
# Process: 2016: RSS = 210.74 MB, VSZ = 6550.928 MB
処理時間
- Benchmark モジュールを使う
-
user, system, total, real の違い
- real: 現実世界の時間
- total: user + system
- user: ユーザー CPU 時間
- Ruby 処理系が働いた CPU 時間
- system: システム CPU 時間
- OS のシステムコール実行に費やした CPU 時間
-
GC の影響を軽減するメソッドがある
- 前提として GC はベンチマークを取る際のノイズになる
- CPU 時間を消費する処理であり、どのタイミングで実行されるか分からない
- リハーサル->GC->本番
- 一回目は実行環境を安定化するためにリハーサルとして実行して
- 二回目は GC 実行後に本番として実行する
- 意図せずリハーサル実行でキャッシュされることに気を付ける
- ボトルネックがDB処理で、リハーサル実行で意図せずキャッシュされてしまったことがあった
- 前提として GC はベンチマークを取る際のノイズになる
require 'benchmark'
array = (1..1000000).map { rand }
Benchmark.bmbm do |x|
x.report("sort") { array.dup.sort }
end
# =>
# Rehearsal ----------------------------------------
# sort 0.328938 0.027635 0.356573 ( 0.356915)
# ------------------------------- total: 0.356573sec
# user system total real
# sort 0.296239 0.002024 0.298263 ( 0.298514)
終わりに
- 計測自体は簡単に行える
- 大事なのは、ベンチマーク取る時に、計測対象以外のノイズがないこと
- 特に意図せずキャッシュが効いているパターン