Ruby1.9を試すその1 - ネイティブスレッド

Tsukasa OISHI

Ruby1.9からThreadがネイティブスレッドを使うようになります。といっても、VMレベルでロックされるようなので、同時に実行されるスレッドは常にひとつです。ただし、IO関連のブロック機能を備えたシステムコールは同時に実行されるようです。

以下のような簡単なIOテストを実行してみました。

require 'benchmark'

threads = []
Benchmark.bm do |x|
  x.report do
    1000.times do |i|
      threads << Thread.new(i) do |t_i|
        File.open("#{t_i}.count", "w") do |f|
          1000.times {|i| f.puts i}
        end
      end
    end
  end
end
threads.each {|t| t.join}

結果。

[tsukasa@ubuntu] $ ruby1.8 aa.rb 
      user     system      total        real
  2.090000   0.490000   2.580000 (  2.579993)
[tsukasa@ubuntu] $ rm -f *.count
[tsukasa@ubuntu] $ ruby aa.rb
      user     system      total        real
  0.750000   0.170000   0.920000 (  0.939997)
[tsukasa@ubuntu] $ [

それから、IOなしのテストをやってみます。

require 'benchmark'

threads = []
Benchmark.bm do |x|
  x.report do
    1000.times do |i|
      threads << Thread.new(i) do |t_i|
        (1..10000).inject(0) {|result,i| result *= i}
      end
    end
  end
end
threads.each {|t| t.join}

結果。

[tsukasa@ubuntu] $ ruby1.8 aa.rb
      user     system      total        real
 14.890000   4.950000  19.840000 ( 19.839974)
[tsukasa@ubuntu] $ ruby aa.rb
      user     system      total        real
  1.530000   0.090000   1.620000 (  1.620000)

全然性能が違いますね。コンテキストスイッチの処理で大きく差が出ているのかな。

Threadを介さずにやってみましょう。

require 'benchmark'

threads = []
Benchmark.bm do |x|
  x.report do
    (1..1000000).inject(0) {|result,i| result *= i}
  end
end
threads.each {|t| t.join}

結果。

[tsukasa@ubuntu] $ ruby1.8 aa.rb
      user     system      total        real
  1.430000   0.470000   1.900000 (  1.899998)
[tsukasa@ubuntu] $ ruby aa.rb
      user     system      total        real
  0.140000   0.000000   0.140000 (  0.140000)

なるほど。VM化による性能の差が大きく出ているみたいです。すばらしい。