速度測定4

昨日1.9をとりあえずコンパイルできたので、
1.9で今までのと同じ比較をする。


先に結論を書いておくと、

速度

基本的に1.8よりも早くなる。
早さは数倍から10倍くらい。
ただ、ほとんど変化しないのもある。

速度比較

今までやってきた速度比較を1.9でも行った。
基本的には1.8と同じ。

個人的感想

(注意:ソースは見ていないので全然ちがうかも)
勝手に予想すると、1.8と1.9では内部のアルゴリズムが同じだから?
YARVは実行時の速度を全体的に早くするが、
これ以上早くするのであれば内部アルゴリズムを変更する必要あり?


速度測定1

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の内部の作りは変わっていない?


速度測定2

__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に追加してくほうが多少早い。


速度測定3

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の方が多少遅い。