速度測定
仕事をしていて、気になりだしたので家で実験。
Rubyのバージョン 1.8.5
each_with_indexが遅い
ソース
#!/usr/bin/env ruby require 'benchmark' 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
結果
$ ./hoge.rb user system total real 0.920000 0.250000 1.170000 ( 1.186080) #=>each + カウンタ 3.070000 0.370000 3.440000 ( 3.459685) #=>each_with_index $ irb irb(main):001:0> 3.459685/1.186080 => 2.91690695399973
each_with_indexの方がeachよりも倍以上遅い。
何故??
map
#!/usr/bin/env ruby require 'benchmark' require 'pp' 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
$ ./hoge.rb user system total real 0.410000 0.160000 0.570000 ( 0.576854) #=>map 0.870000 0.090000 0.960000 ( 0.984442) #=>破壊的 0.570000 0.140000 0.710000 ( 0.723962) #=>新しいArrayに追加
まあ予想通りにmapが早い。
HashとArray
これが今仕事で悩んでいる部分。(細かいことはいえないけど)
データ生成
なんか意味のあるデータが欲しいのでTime.nowを使用する。
#!/usr/bin/env ruby require 'benchmark' require 'pp' 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
$ ./hoge.rb user system total real 1.190000 0.490000 1.680000 ( 3.246003) 2.480000 0.540000 3.020000 ( 3.347390)
結果を見ると、僅かだがHashの方が遅い。
これは予想外の結果。
ネットで調べた限りでは、Hashの方が早いとあったのでそう信じていた。
データ数が多く、全ての領域を使用する場合はHashの方が遅いのか?
まあ、Cで考えれば、Arrayは領域を取得するだけだが、
HashはHash値計算があるので遅いのか?
データ領域が巨大でも一部分しか使用しないのであれば、
圧倒的にHashが早いはずだけど。
メモリ使用率
ある程度の大きさのデータを作成してどのくらいメモリを使用するか。
データはIMbyte。
まずはArray
#!/usr/bin/env ruby #IM n = 1024*1024 ary = Array.new(n) while 1 sleep 10 end
Hash版。
#!/usr/bin/env ruby #IM 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 22434 0.6 1.2 7956 6392 pts/1 S+ 21:49 0:00 ruby ./hoge.rb #=>Array hoge 22462 49.8 5.3 29312 27728 pts/1 S+ 21:50 0:02 ruby ./hoge.rb #=>Hash
CPU使用率はHashの方がtimesで回しているので仕方ないとしても、
明らかにHashの方がメモリ使用量は多い。
結論としてはデータの量が多い場合にはArrayの方が効率がよい可能性が高い。
探索はHashの方が早いらしい。
http://www.loveruby.net/w/OptimizingRubyProgram.html
探索: Array と Hash 重複しない集合を得たいとき。Array に入れておいて uniq! するよりも Hash のキーとして登録していくほうが圧倒的に速い。 hash メソッドの値をうまく設定するのもコツ。 Array#index より Hash のほうが速い。どのくらい速いかというと、 Array のインデックス 0 でヒットしても Hash のほうが速い (ことが多い)。なぜだぁ。