Rubyで実行時間を計測する方法:benchmark

Rubyのプログラムがどの程度処理に時間がかかっているのか、改善するとしたらどの部分がボトルネックになっているかを調べたいときがあります。

ここではRubyで実行時間を計測する方法を2通り解説します。

Ruby標準のbenchmarkを使う

Rubyには標準でbenchmarkというものが用意されているのでそれを使うことができます。

以下は、0からnまでの2乗和を求めるsqメソッドがあり、その実行時間を取得する例です。

require 'benchmark'
include Benchmark

#計測するメソッド
def sq(n)
  ans = 0
  0.upto(n) do |x| ans += x * x end
end

Benchmark.benchmark(CAPTION, 7, FORMAT) do |x|
  x.report("sq:"){ sq(100000) }
end

結果例は、以下のようになります。

              user     system      total        real
sq:       0.010000   0.000000   0.010000 (  0.010339)

のようになります。ここではuser, system, totalのcpu時間と、実際の経過時間が表示されています。

また、上記ではメソッドを計測しましたが、ブロック構文を計測することもできます。

簡略化したbmメソッド

以下は、benchmarkメソッドの簡略化したbmメソッド使った例です。bmメソッドの場合、Benchmarkをincludeする必要はありません。

require 'benchmark'

Benchmark.bm 7 do |x|
  x.report("sq:") do
    n = 100000
    ans = 0
    0.upto(n) do |x| ans += x * x end
  end
end

引数の7は、実行結果のラベル幅を指定するもので、省略した場合は0となります。

複数のプログラムを測る

複数メソッドのプログラムを動かして調べたいときなどの場合は以下のようにします。

sqメソッドの引数を変えた時の実行時間を計測します。

Benchmark.bm do |x|
  x.report("sq(100):") { sq(100) }
  x.report("sq(100000):") { sq(100000) }
end

結果は以下のようになります。

              user     system      total        real
sq(100):  0.000000   0.000000   0.000000 (  0.000022)
sq(100000):  0.010000   0.000000   0.010000 (  0.007545)

Timeクラスを使った簡単な計測

benchmarkを使った実行時間の計測方法について説明しましたが、もっと簡単に計測する場合はTimeクラスが使えます。

プログラムの実行開始時の時刻と実行終了時の時刻を取得し、その差から実行時間を取得するというものです。ただし、この方法ではCPUの処理時間以外の影響を受けやすいので気をつけてください。

def sq(n)
  ans = 0
  0.upto(n) do |x| ans += x * x end
end

start_time = Time.now
n = 100000
sq(n)
end_time = Time.now

colapsed_time = end_time - start_time
puts colapsed_time

処理結果例は以下のように表示されます。

0.010515

Rubyでプログラムの処理時間を測るには経過時間だけでよければ、処理の開始・終了時間の差で求められます。経過時間のほかcpu時間を求めたり複数のプログラムの時間を求めたりするにはbenchmarkが利用できます。

なお、ほかのプロセスが動いている場合にはその影響を受けるので精度よく測るには工夫が必要です。


イベント