Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

benchmarkを使ってみる

前回の記事でbenchmark使えって話だと自己ツッコミしたので、今回の記事ではbenchmarkを試してみる事とします。

対象コードとベンチマーク

require 'date'
require 'benchmark'


def funcA
  (Date.new(2013)..Date.new(9999)).lazy.select {|d| d.day == 13 && d.friday?}.take(10).to_a 
end

def funcB
  (Date.new(2013)..Date.new(9999)).select {|d| d.day == 13 && d.friday?}.take(10)
end

def friday_the_13th(day)
  day.day == 13 && day.friday?
end

def funcC
 (Date.new(2013)..Date.new(9999)).lazy.select {|d| friday_the_13th(d) }.take(10).to_a
end

Benchmark.bm(15) do |x|
  x.report("lazy") {funcA}
  x.report("non lazy") {funcB}
  x.report("lazy with func") {funcC}
end

結果

$ ruby benchmark.rb 
                      user     system      total        real
lazy              0.010000   0.000000   0.010000 (  0.004575)
non lazy          3.460000   0.010000   3.470000 (  3.497499)
lazy with func    0.010000   0.000000   0.010000 (  0.005096)

……なんだこれはタマゲタなぁ……
ものの数行追加するだけで違いがはっきりと分かるようになりました。
その上……今までは早いと思い込んでいた別関数化が、悪影響である事まで判明。*1
ちゃんと試してみるもんですね

参考記録

複数回実行すると、やはり或る程度のバラツキが出ますね。
特に、最初の例は例外的に関数別の方が結果が良くなりました。

$ ruby benchmark.rb 
                      user     system      total        real
lazy              0.000000   0.000000   0.000000 (  0.005214)
non lazy          3.220000   0.010000   3.230000 (  3.231910)
lazy with func    0.000000   0.000000   0.000000 (  0.003674)

$ ruby benchmark.rb 
                      user     system      total        real
lazy              0.000000   0.000000   0.000000 (  0.002276)
non lazy          3.280000   0.010000   3.290000 (  3.296742)
lazy with func    0.000000   0.000000   0.000000 (  0.004000)

$ ruby benchmark.rb 
                      user     system      total        real
lazy              0.010000   0.000000   0.010000 (  0.002349)
non lazy          3.220000   0.010000   3.230000 (  3.243692)
lazy with func    0.010000   0.000000   0.010000 (  0.004159)

$ ruby benchmark.rb 
                      user     system      total        real
lazy              0.010000   0.000000   0.010000 (  0.002608)
non lazy          3.180000   0.010000   3.190000 (  3.195488)
lazy with func    0.000000   0.000000   0.000000 (  0.003540)

$ ruby benchmark.rb 
                      user     system      total        real
lazy              0.000000   0.000000   0.000000 (  0.001655)
non lazy          3.230000   0.010000   3.240000 (  3.256154)
lazy with func    0.010000   0.000000   0.010000 (  0.005210)

$ ruby benchmark.rb 
                      user     system      total        real
lazy              0.000000   0.000000   0.000000 (  0.002429)
non lazy          3.200000   0.010000   3.210000 (  3.218932)
lazy with func    0.010000   0.000000   0.010000 (  0.002948)

編集記録

  • 何度か実行して結果を比較

*1:といっても、優れてる場合も出てるため誤差と言ってしまっても良いレベルですが