Ruby

delete_if がやけに遅いけど、compact! と keep_if は普通。

More than 3 years have passed since last update.

先程「ary-[nil]ary.compact」という記事( http://qiita.com/Nabetani/items/ba6b8eea61e03ce48df7 )を書いたんだけど、そういえば delete_if とかもあったよな、と思い、調べてみたら意外な展開に。

まずはグラフ。縦軸は時間。対数目盛注意。

CRuby は、2.1.3。

JRuby は、1.17.15。

dekeco.png

compact がぐねぐねしているのは、誤差。

まず。

配列のサイズと繰り返す数の積が一定になるようにしているんで、計算量が変わらないことを期待しているんだけど、delete_if はどんどん遅くなっている。

対数目盛なのでわかりにくいかもしれないけど、10倍以上遅くなっている。

keep_ifcompact! は期待通り。なんだろうこれ。

delete_if の後半以外は CRuby が速いけど、delete_if の後半だけは JRuby が速いというところも面白い。

delete_if には副作用のないバージョンがないので、公平を期すために、compact の代わりに dup.compact! にしている。

測定に使ったソースコードは以下のとおり:

require "benchmark"

puts "array size,trial count,label,delete_if,keep_if,compact"
2.to_r.step(7,1.to_r/6) do |ary_size_e|
ary_size =(10**ary_size_e).ceil.to_i
src=Array.new(ary_size){ |n|
n%2==0 ? nil : n
}

trial = (10**7/ary_size ).ceil
print "array size : #{ary_size},trial count : #{trial},,"
Benchmark.benchmark( "", nil, "%u,") do |x|
x.report( "" ){ trial.times{ src.dup.delete_if{ |x| x.nil? } } }
x.report( "" ){ trial.times{ src.dup.keep_if{ |x| ! x.nil? } } }
x.report( "" ){ trial.times{ src.dup.compact! } }
end
puts
end