読者です 読者をやめる 読者になる 読者になる

fastthreadがthread.rbよりどれだけ高速なのか

最近MacBookにPassengerの環境を作ろうとして、gem経由でインストールするとfastthreadというgemがインストールされたので、気になったのでなんだろうとコードを読んでみた。
どうやら標準添付ライブラリ(thread.rb)で提供されているQueueやSizedQueueをそのまま、Ruby拡張したものだ。
つまり、Cで記述されている。

そこで、thread.rbとfasttreadを比較するbenchmarkを計測してみた。
よくある、Queueを使う簡単なConsumer/Producerパターンを検証コードとした。

# coding: utf-8

require 'rubygems' if RUBY_VERSION  < "1.9"
require 'benchmark'

N = 1000000

def consumer_producer
  queue = Queue.new
  producer = Thread.new do
    N.times do |i|
      queue << i
    end
  end
  consumer = Thread.new do
    loop {
      break if !producer.alive? && queue.empty?
      queue.pop
    }
  end
  consumer.join
end

Benchmark.bmbm do |benchmark|
  require 'thread'
  benchmark.report("thread:") {
    consumer_producer
  }
  require 'fastthread'
  benchmark.report("fastthread:") {
    consumer_producer
  }
end

検証環境はWindows(cygwin)とMac(Core2 Duo 2.2GHz)で、実行すると次のような結果になった。

cygwin$ <ruby thread.rb
Rehearsal -----------------------------------------------
thread:       1.154000   0.031000   1.185000 (  1.193000)
fastthread:   1.373000   0.094000   1.467000 (  1.473000)
-------------------------------------- total: 2.652000sec

                  user     system      total        real
thread:       1.342000   0.000000   1.342000 (  1.380000)
fastthread:   1.373000   0.015000   1.388000 (  1.381000)

Macでの実行結果。

osx$ <ruby thread.rb
Rehearsal -----------------------------------------------
thread:       2.450000   0.020000   2.470000 (  2.463525)
fastthread:   2.310000   0.050000   2.360000 (  2.380355)
-------------------------------------- total: 4.830000sec

                  user     system      total        real
thread:       2.200000   0.010000   2.210000 (  2.206227)
fastthread:   2.180000   0.010000   2.190000 (  2.196245)

fastthread使っても、threadのままでもあんまりかわらない。誤差の範囲ぽい。