enumerator
enumerator - #生存戦略 、それは - subtechを読んで、たしかRuby 1.9では以下のように書けるとどこかで読んだ気がしたので実際に試したらちゃんと動いた。これはかっこいい。
[1, 1, 1].map.with_index {|e, i| e + i} # => [1, 2, 3]
なんとなくeach_with_indexよりもeach.with_indexの方が重そうに感じる(見た目が多段だから?)けど、これは実際にベンチマークとってみたい。
require 'benchmark' COUNT = 1000 range = (1..1000) array = range.to_a Benchmark.bmbm do |x| x.report("range.e_w_i") do COUNT.times do range.each_with_index do |e, i| e + i end end end x.report("range.e.w_i") do COUNT.times do range.each.with_index do |e, i| e + i end end end x.report("array.e_w_i") do COUNT.times do array.each_with_index do |e, i| e + i end end end x.report("array.e.w_i") do COUNT.times do array.each.with_index do |e, i| e + i end end end end
まずは会社のCygwin環境にて。
ruby 1.9.0 (2006-08-04) [i386-cygwin] Rehearsal ----------------------------------------------- range.e_w_i 3.125000 0.015000 3.140000 ( 3.168000) range.e.w_i 3.110000 0.000000 3.110000 ( 3.127000) array.e_w_i 3.140000 0.000000 3.140000 ( 3.159000) array.e.w_i 3.094000 0.000000 3.094000 ( 3.124000) ------------------------------------- total: 12.484000sec user system total real range.e_w_i 3.125000 0.000000 3.125000 ( 3.157000) range.e.w_i 3.078000 0.016000 3.094000 ( 3.102000) array.e_w_i 3.141000 0.000000 3.141000 ( 3.162000) array.e.w_i 3.062000 0.000000 3.062000 ( 3.096000)
あまり差がない、というかむしろeach.with_indexの方が速い様に見える。
自宅のFreeBSDマシンでも試すべきかと思いつつ、なんかピンときたので、COUNTを100000、rangeを(1..100)に変えて再度試した。
ruby 1.9.0 (2006-08-04) [i386-cygwin] Rehearsal ----------------------------------------------- range.e_w_i 3.360000 0.000000 3.360000 ( 3.404000) range.e.w_i 3.750000 0.015000 3.765000 ( 3.786000) array.e_w_i 3.328000 0.000000 3.328000 ( 3.359000) array.e.w_i 3.703000 0.000000 3.703000 ( 3.742000) ------------------------------------- total: 14.156000sec user system total real range.e_w_i 3.375000 0.000000 3.375000 ( 3.382000) range.e.w_i 3.828000 0.000000 3.828000 ( 3.840000) array.e_w_i 3.359000 0.000000 3.359000 ( 3.384000) array.e.w_i 3.703000 0.000000 3.703000 ( 3.750000)
each_with_indexの方が速くなった。これはEnumerable::Enumeratorオブジェクトの生成コストの問題のような気がする。
適当なベンチマークを適当なマシン上で動かした結果なので信頼度は低いが、思ったより強烈な差は確認できなかったので、どちらを使ってもそんなに変わんないんじゃないかなあ、という結論にしてみる。一安心したところで仕事に戻ります。