module Benchmark

要約

ベンチマークを取るためのモジュールです。

目次

モジュール関数
定数

モジュール関数

benchmark(caption = "", label_width = nil, fmtstr = nil, *labels) {|rep| ...} -> bool[permalink][rdoc]

Benchmark::Report オブジェクトを生成し、それを引数として与えられたブロックを実行します。

基本的には以下のように使います。ブロックが Benchmark::Tms オブジェクトの配列を返した場合は、それらの数値も追加の行に表示されます。

[PARAM] caption:
レポートの一行目に表示する文字列を指定します。
[PARAM] label_width:
ラベルの幅を指定します。
[PARAM] fmtstr:
フォーマット文字列を指定します。この引数を省略すると Benchmark::FORMAT が使用されます。
[PARAM] labels:
ブロックが Benchmark::Tms オブジェクトの配列を返す場合に指定します。
[RETURN]
STDIN.sync の値を返すだけなので返り値に意味はありません。

フォーマット文字列

フォーマット文字列として以下が使用できます。

%u

user CPU time で置き換えられます。Benchmark::Tms#utime

%y

system CPU time で置き換えられます(Mnemonic: y of "s*y*stem")。Benchmark::Tms#stime

%U

子プロセスの user CPU time で置き換えられます。Benchmark::Tms#cutime

%Y

子プロセスの system CPU time で置き換えられます。Benchmark::Tms#cstime

%t

total CPU time で置き換えられます。Benchmark::Tms#total

%r

実経過時間で置き換えられます。Benchmark::Tms#real

%n

ラベルで置き換えられます(Mnemonic: n of "*n*ame")。Benchmark::Tms#label

require 'benchmark'

n = 50000

# これは
#    Benchmark.bm(7, ">total:", ">avg:") do |x| ... end
# と同じ
Benchmark.benchmark(" "*7 + Benchmark::CAPTION,
                    7,
                    Benchmark::FMTSTR,
                    ">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:     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)
bm(label_width = 0, *labels) {|rep| ... } -> bool[permalink][rdoc]

Benchmark.#benchmark メソッドの引数を簡略化したものです。

Benchmark.#benchmark メソッドと同様に働きます。

[PARAM] label_width:
ラベルの幅を指定します。
[PARAM] labels:
ブロックが Benchmark::Tms オブジェクトの配列を返す場合に指定します。
[RETURN]
STDIN.sync の値を返すだけなので返り値に意味はありません。

例:

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)

以下のようにも書けます。

require 'benchmark'

n = 50000
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)

集計を付けた場合

require 'benchmark'

n = 50000
Benchmark.bm(7) 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.040000   0.000000   0.040000 (  0.141902)
times:   0.010000   0.000000   0.010000 (  0.043335)
upto:    0.020000   0.000000   0.020000 (  0.089806)
>total:  0.070000   0.000000   0.070000 (  0.275044)
>avg:    0.023333   0.000000   0.023333 (  0.091681)

[SEE_ALSO] Benchmark.#benchmark

bmbm(width = 0) {|job| ... } -> [Benchmark::Tms][permalink][rdoc]

Benchmark::Job オブジェクトを生成して、それを引数として与えられたブロックを実行します。

ベンチマークの結果は GC の影響によって歪められてしまうことがあります。このメソッドは与えられたブロックを二度実行する事によってこの影響を最小化します。一回目は実行環境を安定化するためにリハーサルとして実行します。二回目は本番として実行します。

二回目のブロック実行の前に GC.start を実行しますが、この実行時間は計測には含まれません。しかし、実際にはこのメソッドを使用しても、GC などの影響を分離することは保証されません。

[PARAM] width:
ラベルの幅を指定します。
require 'benchmark'

array = (1..1000000).map { rand }

Benchmark.bmbm do |x|
  x.report("sort!") { array.dup.sort! }
  x.report("sort")  { array.dup.sort  }
end

#=>

Rehearsal -----------------------------------------
sort!  11.928000   0.010000  11.938000 ( 12.756000)
sort   13.048000   0.020000  13.068000 ( 13.857000)
------------------------------- total: 25.006000sec

            user     system      total        real
sort!  12.959000   0.010000  12.969000 ( 13.793000)
sort   12.007000   0.000000  12.007000 ( 12.791000)
measure(label = "") { ... } -> Benchmark::Tms[permalink][rdoc]

与えられたブロックを実行して、経過した時間を Process.#times で計り、 Benchmark::Tms オブジェクトを生成して返します。

Benchmark::Tms オブジェクトには to_s が定義されているので、基本的には以下のように使います。

require 'benchmark'

puts Benchmark::CAPTION
puts Benchmark.measure { "a"*1_000_000 }

#=>

    user     system      total        real
1.166667   0.050000   1.216667 (  0.571355)
realtime { ... } -> Float[permalink][rdoc]

与えられたブロックを評価して実行時間を計測して返します。

定数

BENCHMARK_VERSION -> String[permalink][rdoc]

benchmark ライブラリのバージョンを表します。

CAPTION -> String[permalink][rdoc]

Benchmark.#bm の内部などで使用されます。

実際の定義は Benchmark::Tms::CAPTION でされています。

[SEE_ALSO] Benchmark::Tms::CAPTION

FORMAT -> String[permalink][rdoc]

Benchmark.#benchmark の第三引数のデフォルト値。

%u

user CPU time で置き換えられます。Benchmark::Tms#utime

%y

system CPU time で置き換えられます(Mnemonic: y of "s*y*stem")。Benchmark::Tms#stime

%U

子プロセスの user CPU time で置き換えられます。Benchmark::Tms#cutime

%Y

子プロセスの system CPU time で置き換えられます。Benchmark::Tms#cstime

%t

total CPU time で置き換えられます。Benchmark::Tms#total

%r

実経過時間で置き換えられます。Benchmark::Tms#real

%n

ラベルで置き換えられます(Mnemonic: n of "*n*ame")。Benchmark::Tms#label

上記のフォーマット文字列を使用しています。この定数の内容は以下の通りです。

"%10.6u %10.6y %10.6t %10.6r\n"

[SEE_ALSO] Benchmark.#benchmark, Benchmark::Tms::FORMAT