Posted at

CRuby 2.1 が速いとは限らない

More than 5 years have passed since last update.

先日 ruby と jruby の速度の差( http://qiita.com/Nabetani/items/9776d99d09476d07c9e2 )という記事を書いて、CRuby 2.1 がすごいという印象を与えたと思うんだけど、今度はそうじゃないよという記事。

前回と同様、調査対象は


  • ruby 1.9

  • ruby 2.0

  • ruby 2.1

  • jruby1.7.12 --1.9

  • jruby1.7.12 --2.0

の5つ。


わかったこと


  • やることが違えば、何が速いかも違う。諸行無常。

  • CRuby の 1.9 や 2.0 よりも 2.1 が遅いこともある。意外。


結果

横軸は時間なので、長いほうが遅い。

vench.png

選んだ処理は思いつくまま。

あんまり込み入ってなくて、そのわりにバージョンによって差がでそうなものを適当に書いた。

2.1 が遅くなるものを選んだってわけじゃない。

以下、リハーサルは省略。


ruby 1.9

"ruby 1.9.3p545 (2014-02-24 revision 45159) [x86_64-darwin13.0.0]"

size : 2000
user system total real
pack_unpack 1.200000 0.020000 1.220000 ( 1.222390)
hugenum 0.840000 0.050000 0.890000 ( 0.885420)
delete_if_and_push 5.930000 0.000000 5.930000 ( 5.935082)
modify_string 3.310000 0.010000 3.320000 ( 3.314836)


ruby 2.0

"ruby 2.0.0p481 (2014-05-08 revision 45883) [x86_64-darwin13.3.0]"

size : 2000
user system total real
pack_unpack 1.230000 0.050000 1.280000 ( 1.274881)
hugenum 0.940000 0.050000 0.990000 ( 0.991847)
delete_if_and_push 5.760000 0.000000 5.760000 ( 5.763749)
modify_string 3.530000 0.000000 3.530000 ( 3.536681)


ruby 2.1

"ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]"

size : 2000
user system total real
pack_unpack 2.470000 0.050000 2.520000 ( 2.518461)
hugenum 0.850000 0.010000 0.860000 ( 0.860112)
delete_if_and_push 7.220000 0.010000 7.230000 ( 7.229943)
modify_string 3.530000 0.000000 3.530000 ( 3.526038)


jruby1.7.12 --1.9

"jruby 1.7.12 (1.9.3p392) 2014-04-15 643e292 on Java HotSpot(TM) 64-Bit Server VM 1.7.0_07-b10 [darwin-x86_64]"

size : 2000
user system total real
pack_unpack 1.730000 0.010000 1.740000 ( 1.710000)
hugenum 2.510000 0.000000 2.510000 ( 2.491000)
delete_if_and_push 2.600000 0.010000 2.610000 ( 2.554000)
modify_string 1.820000 0.010000 1.830000 ( 1.822000)


jruby1.7.12 --2.0

"jruby 1.7.12 (2.0.0p195) 2014-04-15 643e292 on Java HotSpot(TM) 64-Bit Server VM 1.7.0_07-b10 [darwin-x86_64]"

size : 2000
user system total real
pack_unpack 1.760000 0.010000 1.770000 ( 1.744000)
hugenum 2.530000 0.000000 2.530000 ( 2.518000)
delete_if_and_push 3.320000 0.030000 3.350000 ( 2.883000)
modify_string 1.850000 0.000000 1.850000 ( 1.847000)


利用したプログラム

#encode:utf-8

(p RUBY_DESCRIPTION) rescue p "1.8.x or former"
require "benchmark"

def pack_unpack(size)
s=Array.new(30000){ [*"a".."z"].sample }.join
size.times do
s=[s].pack("m").unpack("m").first
s=s.unpack("N*").pack("V*")
end
end

def hugenum(size)
a=10
size.times do
a=(a**a % 8191 )+10
end
end

def delete_if_and_push(size)
s=[]
(2..size).each do |x|
s.each{ |e| e<<1 unless e[0] % x ==0 }
s.delete_if{ |e| e[0] % x ==0 }
s<<(s.size.to_s*(s.size+1)) while s.size<size
end
end

def modify_string( size )
srand 1
s=[*"\u1d400".."\u1d500"].zip( (?a..?z).cycle ).flatten.join
(size/5).times do
s[rand(s.size)]="a\u1f200"*size
end
end

def run_bench( size )
puts "size : #{size}"

m=[ :pack_unpack, :hugenum, :delete_if_and_push, :modify_string ]
len = m.map(&:to_s).map(&:size).max
Benchmark.bmbm(len) do |x|
m.each do |s|
x.report(s.to_s){
self.send(s, size)
}
end
end
end

run_bench( 2000 )


結論

測ってみないとわからない。