速度測定4
昨日1.9をとりあえずコンパイルできたので、
1.9で今までのと同じ比較をする。
先に結論を書いておくと、
速度
基本的に1.8よりも早くなる。
早さは数倍から10倍くらい。
ただ、ほとんど変化しないのもある。
速度比較
今までやってきた速度比較を1.9でも行った。
基本的には1.8と同じ。
個人的感想
(注意:ソースは見ていないので全然ちがうかも)
勝手に予想すると、1.8と1.9では内部のアルゴリズムが同じだから?
YARVは実行時の速度を全体的に早くするが、
これ以上早くするのであれば内部アルゴリズムを変更する必要あり?
each_with_index
1.8では each>each_with_index の順で早かった。
n = 500000 Benchmark.bm do |x| ary = Array.new(n) x.report{ i = 0 ary.each do |val| val = 100 i += 1 end } x.report{ ary.each_with_index do |val, i| val = 100 end } end
user system total real 0.200000 0.010000 0.210000 ( 0.231885) 0.200000 0.000000 0.200000 ( 0.360460)
YARVは素晴らしい。
1.8よりも10倍以上早くなっている。
けれど結局each_with_indexの方が遅い。
map
1.8では map>破壊的>新しいArrayに追加 の順で早いかった。
n = 500000 Benchmark.bm do |x| ary = Array.new(n) x.report{ ary.map{100} } #破壊的 x.report{ i = 0 ary.each do ary[i] = 100 i += 1 end } #新しいArrayに追加 x.report{ ret = [] ary.each do ret << 100 end } end
user system total real 0.140000 0.020000 0.160000 ( 0.178280) 0.280000 0.000000 0.280000 ( 0.460763) 0.200000 0.000000 0.200000 ( 0.425925)
全体的に早くなったが、結局mapが早い。
HashとArray
データ生成
1.8では Array>Hash の順で早かった。
n = 500000 Benchmark.bm do |x| ary = Array.new(n) h = Hash.new x.report{ ary.map{Time.now} } x.report{ n.times do |i| h[i] = Time.now end } end
#1.8 user system total real 1.190000 0.490000 1.680000 ( 3.246003) 2.480000 0.540000 3.020000 ( 3.347390) #1.9 user system total real 0.770000 0.350000 1.120000 ( 1.656341) 1.880000 0.300000 2.180000 ( 3.487237)
結局早さの順番は変わらない。
しかも、今までとは違い,Arrayは半分くらいの速度UP
Hashに至っては速度がほとんど変化がない。
Hashは内部アルゴリズムを変えていないので速度が変わらないと
ソースを見ないで予想しておく。
メモリ使用率
1.8では Array>Hash でメモリ使用率が少なかった。
Array版
n = 1024*1024 ary = Array.new(n) while 1 sleep 10 end
Hash版
n = 1024*1024 h = Hash.new(n) n.times do |i| h[i] = 100 end while 1 sleep 10 end
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND hoge 25352 0.6 1.2 7956 6388 pts/1 S+ 13:20 0:00 ruby hoge.rb hoge 25388 25.6 5.3 29304 27724 pts/1 S+ 13:21 0:03 ruby hoge.rb
結局Hashの方がメモリを使用率が高い。
しかも1.8メモリ使用率が全然変化してない。
ArrayとHashの内部の作りは変わっていない?
__send__
1.8では メソッドの通常呼び出し>__send__>lamda の順で早かった。
n = 500000 Benchmark.bm do |x| ary = Array.new(n) x.report{ def hoge "hoge" end n.times do hoge end } x.report{ def hoge "hoge" end n.times do __send__(:hoge) end } x.report{ hoge = lambda{ "hoge" } n.times do hoge.call end } end
user system total real 0.590000 0.010000 0.600000 ( 0.999928) 0.600000 0.020000 0.620000 ( 1.045452) 0.740000 0.030000 0.770000 ( 1.427803)
全体的に速度は改善しているけど、結局lambdaが一番遅い。
Array#each
1.8では eachで値を取る>取らない の順で早かった。
n = 500000 Benchmark.bm do |x| ary = Array.new(n) x.report{ ary.each do |obj| Time.now end } x.report{ ary.each do Time.now end } end
user system total real 1.010000 0.230000 1.240000 ( 2.013669) 1.060000 0.180000 1.240000 ( 2.017885)
ほとんど違いがない。
これはYARVのおかげ?
それとも1.8とほとんど速度差がないので誤差の範囲?
Arrayに値を設定
1.8ではほとんど差がなかった。
n = 500000 Benchmark.bm do |x| ary = Array.new(n) x.report{ n.times do |i| ary[i] = 100 end } x.report{ a = [] n.times do |i| a << 100 end } end
user system total real 0.270000 0.000000 0.270000 ( 0.462763) 0.190000 0.010000 0.200000 ( 0.410374)
全体的に明らかに早くなった。
速度比較としては、既にあるArrayに値を設定するより、
空のArrayに追加してくほうが多少早い。
inject
1.8では injectを使用しない > 使用する の順で早かった。
n = 500000 Benchmark.bm do |x| ary = Array.new(n){1} x.report{ num = 0 ary.each do |i| num += i end } x.report{ ary.inject(0){|result, item|result += item} } end
user system total real 0.180000 0.000000 0.180000 ( 0.384614) 0.230000 0.000000 0.230000 ( 0.434350)
全体的に早くなったが、結局injectの方が多少遅い。