Rubyのプログラムがどの程度処理に時間がかかっているのか、改善するとしたらどの部分がボトルネックになっているかを調べたいときがあります。
ここではRubyで実行時間を計測する方法を2通り解説します。
Ruby標準のbenchmarkを使う
Rubyには標準でbenchmarkというものが用意されているのでそれを使うことができます。
以下は、0からnまでの2乗和を求めるsqメソッドがあり、その実行時間を取得する例です。
1 2 3 4 5 6 7 8 9 10 11 12 |
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 |
結果例は、以下のようになります。
1 2 |
user system total real sq: 0.010000 0.000000 0.010000 ( 0.010339) |
のようになります。ここではuser, system, totalのcpu時間と、実際の経過時間が表示されています。
また、上記ではメソッドを計測しましたが、ブロック構文を計測することもできます。
簡略化したbmメソッド
以下は、benchmarkメソッドの簡略化したbmメソッド使った例です。bmメソッドの場合、Benchmarkをincludeする必要はありません。
1 2 3 4 5 6 7 8 9 |
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メソッドの引数を変えた時の実行時間を計測します。
1 2 3 4 |
Benchmark.bm do |x| x.report("sq(100):") { sq(100) } x.report("sq(100000):") { sq(100000) } end |
結果は以下のようになります。
1 2 3 |
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の処理時間以外の影響を受けやすいので気をつけてください。
1 2 3 4 5 6 7 8 9 10 11 12 |
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 |
処理結果例は以下のように表示されます。
1 |
0.010515 |
Rubyでプログラムの処理時間を測るには経過時間だけでよければ、処理の開始・終了時間の差で求められます。経過時間のほかcpu時間を求めたり複数のプログラムの時間を求めたりするにはbenchmarkが利用できます。
なお、ほかのプロセスが動いている場合にはその影響を受けるので精度よく測るには工夫が必要です。