最新

val it : α → α = fun

<<  2007/05  >>

2007/05/30 rubyでリングベンチマーク

ふと Fiber をさわってみたくなって、前に別のところで試したリングベンチマークというのをやっていることにしました。

リングベンチマークというのはどういうのかというと、 N 個のノード(プロセス)を用意して、1番のノードは2番に、2番のノードは3番に……というようにメッセージを送信する。で、 N 番のノードはまた1番に戻る。で、 M 回ほどメッセージの送信を終えたらおもむろに終了する。これのパフォーマンスを調べなさいっていう話。

まあ、あからさまに Erlang に有利なベンチマークなんですが(笑)。

Fiber を使うとこんな感じでしょうか。

require 'benchmark'

class Node
  attr_accessor :oth
  def initialize(count, oth=nil)
    @oth = oth
    @node = Fiber.new do
      count.times do |i|
        # puts "sending message [#{i}]"
        v = @oth.pass(:message)
      end
    end
  end
  def pass(v=nil)
    @node.pass(v)
  end
end

class RingNodes
  def initialize(nodes, count)
    @nodes = Array.new(nodes)
    @nodes[nodes-1] = Node.new(count)
    (nodes-1).downto(0) do |i|
      @nodes[i] = Node.new(count, @nodes[i+1])
    end
    @nodes[nodes-1].oth = @nodes[0]
  end
  def start
    @nodes[0].pass
  end
end

def main(nodes, count)
  Benchmark.bm(15) do |x|
    ring = nil
    x.report("initialize") { ring = RingNodes.new(nodes, count) }
    x.report("passing") { ring.start } 
  end
end

nodes = (ARGV[0] || 10).to_i
count = (ARGV[1] || 10).to_i

main(nodes, count)

実行結果はこんな感じでした。

% /usr/local/ruby-1.9/bin/ruby19 ~/ring.rb 10 100
                     user     system      total        real
initialize       0.000000   0.000000   0.000000 (  0.000319)
passing          0.000000   0.000000   0.000000 (  0.003591)
% /usr/local/ruby-1.9/bin/ruby19 ~/ring.rb 100 100
                     user     system      total        real
initialize       0.000000   0.000000   0.000000 (  0.002868)
passing          0.030000   0.000000   0.030000 (  0.038393)
% /usr/local/ruby-1.9/bin/ruby19 ~/ring.rb 1000 100
                     user     system      total        real
initialize       0.040000   0.020000   0.060000 (  0.060228)
passing          0.610000   0.010000   0.620000 (  0.639878)
% /usr/local/ruby-1.9/bin/ruby19 ~/ring.rb 5000 100
                     user     system      total        real
initialize       0.970000   0.160000   1.130000 (  1.142228)
passing          3.690000   0.060000   3.750000 (  3.836600)
% /usr/local/ruby-1.9/bin/ruby19 ~/ring.rb 10000 100
                     user     system      total        real
initialize       4.520000   0.450000   4.970000 (  5.042758)
passing          8.600000   0.140000   8.740000 (  8.966811)
% /usr/local/ruby-1.9/bin/ruby19 ~/ring.rb 20000 100
                     user     system      total        real
initialize      33.880000   1.470000  35.350000 ( 35.640199)
passing         28.600000   0.310000  28.910000 ( 29.607706)

だんだんキツくなっていくとはいえ、1万fiberくらいは余裕みたいですね。 Fiber かっこいい(←これ言ってみたかっただけ)。