Railsチュートリアルにてbenchmarkを知り、理解を深めるためにアウトプット。
benchmarkとは
辞書によれば
① 測量で,高低の基準となる水準点。計測指標。
② ものごとの基準となるもの。
プログラミングでは、ある特定の機能を果たすプログラムを書くときに複数の手法が存在した場合、どの手法が最も効率的かを知ることで、「ベンチマークをとる」という表現をする。
Rubyのbenchmarkはプログラム実行時の処理速度を計測できる。
サンプルコード
リファレンスの例となっていたコードが以下のコード。
これは、for、times、uptoの繰り返し処理の速度の速さをそれぞれ調べている。
require 'benchmark'
n = 50000 # 何回実行するか
Benchmark.benchmark(" "*7 + Benchmark::CAPTION,
7,
Benchmark::FORMAT,
">total:",
">avg:") do |x|
tf = x.report("for:") { for i in 1..n; a = "1"; end }
tf = 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: 1.016667 0.016667 1.033333 ( 0.485749)
# times: 1.450000 0.016667 1.466667 ( 0.681367)
# upto: 1.533333 0.000000 1.533333 ( 0.722166)
# >total: 4.000000 0.033333 4.033333 ( 1.889282)
# >avg: 1.333333 0.011111 1.344444 ( 0.629761)
Benchmark.benchmarkでBenchmark::Reportオブジェクトが作られる。
(Benchmark::Reportは計測結果を管理し、出力するための仕組みを持っているRubyのクラス)
Benchmark.benchmarkの引数は結果の表示を見やすく整えるための細かいフォーマット指定の役割。
第一引数について
(" "*7 + Benchmark::CAPTION,
Benchmark::CAPTIONには出力時のヘッダーである以下の文字列を指定してる。
user system total real
" "*7によってヘッダーの先頭にスペースが7つ入るため出力結果が以下のように成形されている。
user system total real
第二引数はラベル(forやtimesなど)の幅を7文字分のスペースをとるように指定。
第三引数は計測結果を出力する際のフォーマット指定でデフォルトは
user: ユーザーCPU時間
system: システムCPU時間
total: 合計CPU時間
real: 実行時間
となっている。
第四引数、第五引数は出力結果のラベルを追加している。
サンプルコードではtotalとavgの計測も行っているため。
ブロック内について
|x|はBenchmark::Reportのオブジェクト
reportはBenchmark::Reportのインスタンスメソッドで、x.reportはブロック内{ for i in 1..n; a = "1"; end }の処理を実行し、その処理にかかった時間を計測している。
実行時間を出力する結果はbenchmark::Tmsオブジェクトとして記録される。
(Benchmark::Tmsは計測結果を保持するオブジェクトで以下のデータを格納する)
utime: User CPU time
stime: System CPU time
cutime: 子プロセスの User CPU time
cstime: 子プロセスの Sytem CPU time
real: 実経過時間
label: ラベル
[tf+tt+tu, (tf+tt+tu)/3]
はtf,tt,tuを合計と平均を計算した新しいBenchmark::Tmsオブジェクト。
Benchmark.benchmarkのブロックは実行後、戻り値をチェックし、戻り値が配列の場合、各要素が計測結果に追加される。
まとめ
今日はここまで。
処理内容がわかったところで結果と使い方はまた別記事で記載。