👀
【Ruby】まとめでよく見る処理速度の計測方法・見方
記事を書くにあたり、Rubyの処理速度の計測方法分からなかったので調べてみました。
標準ライブラリのbenchmark
Rubyにはbenchmarkライブラリという名前の通りベンチマークを取るための標準ライブラリがあるらしい。
基本的にBenchmarkモジュールのbmメソッドで良さそう。
benchmarkライブラリ
bmメソッド
使い方
コード
require 'benchmark'
n = 50000
Benchmark.bm do |x|
x.report { for i in 1..n; a = "1"; end }
x.report { n.times do ; a = "1"; end }
x.report { 1.upto(n) do ; a = "1"; end }
end
#=>
# user system total real
# 1.033333 0.016667 1.016667 ( 0.492106)
# 1.483333 0.000000 1.483333 ( 0.694605)
# 1.516667 0.000000 1.516667 ( 0.711077)
どう見るの?
結論から言うと、目的によってuser と total のどちらかを見れば良さそう。
それぞれざっくりこんな感じらしいです。
user
ユーザー CPU 時間
ユーザープログラムの実行に費やした CPU 時間。この場合、Ruby スクリプトを実行すべく Ruby 処理系が働いたぶんの CPU 時間のこと。
system
システム CPU 時間
OS はファイルの読み書きなどの基本的な機能を「システムコール」という形で提供しているが、プログラムがそれを呼び出しその実行に費やした CPU 時間をこう呼ぶらしい。
total
userとsystemの和
real
処理の開始から終了までの現実の経過時間
Timeクラスを使用した場合と同じなので、待機時間が含まれたりネットワークの影響も受けてしまうため、見る必要はない。
結果を見やすくする
bmメソッドは第一引数でラベルの幅を設定できる。
reportで見やすいようにラベルを設定しつつ、bmメソッドの引数にラベルの最大文字数+スペース分を入れると見やすそう。
# 設定略
Benchmark.bm(7) do |x|
x.report("for:") { for i in 1..n; a = "1"; end }
x.report("times:") { n.times do ; a = "1"; end }
x.report("upto:") { 1.upto(n) do ; a = "1"; end }
end
#=>
# user system total real
# for: 1.050000 0.000000 1.050000 ( 0.503462)
# times: 1.533333 0.016667 1.550000 ( 0.735473)
# upto: 1.500000 0.016667 1.516667 ( 0.711239)
第二引数以降はブロックが配列を返す場合のラベルを設定できる。
合計や、平均を出したい場合に便利
# 設定略
Benchmark.bm(7, ">total:", ">avg:") do |x|
tf = x.report("for:") { for i in 1..n; a = "1"; end }
tt = x.report("times:") { n.times do ; a = "1"; end }
tu = x.report("upto:") { 1.upto(n) do ; a = "1"; end }
[tf + tt + tu, (tf + tt + tu) / 3]
end
#=>
# user system total real
# for: 0.001467 0.004727 0.006194 ( 0.006193)
# times: 0.003814 0.000000 0.003814 ( 0.003814)
# upto: 0.003855 0.000003 0.003858 ( 0.003859)
# >total: 0.009136 0.004730 0.013866 ( 0.013867)
# >avg: 0.003045 0.001577 0.004622 ( 0.004622)
参考記事
Discussion