require 'benchmark'
project_lib_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
$LOAD_PATH.unshift(project_lib_path)
require 'agent'

$size = (ARGV.pop || 0).to_i

def generate(channels)
  ch = channel!(Integer, $size)
  channels << ch
  go!{ i = 1; loop { ch << i+= 1} }

  return ch
end

def filter(in_channel, prime, channels)
  out = channel!(Integer, $size)
  channels << out

  go! do
    loop do
      i, _ = in_channel.receive
      out << i if (i % prime) != 0
    end
  end

  return out
end

def sieve(channels)
  out = channel!(Integer, $size)
  channels << out

  go! do
    ch = generate(channels)
    loop do
      prime, _ = ch.receive
      out << prime
      ch = filter(ch, prime, channels)
    end
  end

  return out
end

################
################

nth_prime = 150
concurrency = 5
channels = []

puts "#{nth_prime}'s prime, #{concurrency} goroutines, channel buffer size is #{$size}"

Benchmark.bm(7) do |x|
  x.report("receive") do
    runners = []

    concurrency.times do |n|
      runners << go! do
        primes = sieve(channels)
        nth_prime.times { primes.receive }
      end
    end

    runners.map {|t| t.join}
  end
end

puts

channels.each(&:close)

__END__

The setup:
  13" Macbook Air
  OSX Lion 10.7.3
  1.8 GHz Intel Core i7
  4 GB 1333 MHz DDR3
  SSD
  Terminal w/ OSX Lion's system ruby by default

The command:
  benchmark/multi_ruby_bench.sh

The results:

ruby 1.8.7 (2010-01-10 patchlevel 249) [universal-darwin11.0]

150's prime, 5 goroutines, channel buffer size is 0
             user     system      total        real
receive 27.100000   0.290000  27.390000 ( 27.324909)

150's prime, 5 goroutines, channel buffer size is 1
             user     system      total        real
receive 24.690000   0.280000  24.970000 ( 24.910035)

150's prime, 5 goroutines, channel buffer size is 2
             user     system      total        real
receive 24.730000   0.280000  25.010000 ( 24.946830)

150's prime, 5 goroutines, channel buffer size is 3
             user     system      total        real
receive 25.010000   0.290000  25.300000 ( 25.238002)


ruby 1.8.7 (2012-02-08 patchlevel 358) [i686-darwin11.3.0]

150's prime, 5 goroutines, channel buffer size is 0
             user     system      total        real
receive 17.890000   0.090000  17.980000 ( 17.984755)

150's prime, 5 goroutines, channel buffer size is 1
             user     system      total        real
receive 17.030000   0.090000  17.120000 ( 17.131916)

150's prime, 5 goroutines, channel buffer size is 2
             user     system      total        real
receive 17.060000   0.090000  17.150000 ( 17.168336)

150's prime, 5 goroutines, channel buffer size is 3
             user     system      total        real
receive 17.090000   0.100000  17.190000 ( 17.187443)


ruby 1.9.2p318 (2012-02-14 revision 34678) [x86_64-darwin11.3.0]

150's prime, 5 goroutines, channel buffer size is 0
             user     system      total        real
receive  5.410000   2.360000   7.770000 (  7.241433)

150's prime, 5 goroutines, channel buffer size is 1
             user     system      total        real
receive  5.270000   1.980000   7.250000 (  6.817536)

150's prime, 5 goroutines, channel buffer size is 2
             user     system      total        real
receive  5.330000   2.030000   7.360000 (  6.918912)

150's prime, 5 goroutines, channel buffer size is 3
             user     system      total        real
receive  5.340000   1.950000   7.290000 (  6.864300)


ruby 1.9.3p125 (2012-02-16 revision 34643) [x86_64-darwin11.3.0]

150's prime, 5 goroutines, channel buffer size is 0
              user     system      total        real
receive   6.470000   5.220000  11.690000 (  8.803085)

150's prime, 5 goroutines, channel buffer size is 1
              user     system      total        real
receive   6.390000   4.190000  10.580000 (  8.248593)

150's prime, 5 goroutines, channel buffer size is 2
              user     system      total        real
receive   6.240000   3.760000  10.000000 (  7.936199)

150's prime, 5 goroutines, channel buffer size is 3
              user     system      total        real
receive   6.000000   3.200000   9.200000 (  7.461371)


jruby 1.6.7 (ruby-1.8.7-p357) (2012-02-22 3e82bc8) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_29) [darwin-x86_64-java]

150's prime, 5 goroutines, channel buffer size is 0
             user     system      total        real
receive  9.672000   0.000000   9.672000 (  9.637000)

150's prime, 5 goroutines, channel buffer size is 1
             user     system      total        real
receive 12.528000   0.000000  12.528000 ( 12.494000)

150's prime, 5 goroutines, channel buffer size is 2
             user     system      total        real
receive 13.191000   0.000000  13.191000 ( 13.150000)

150's prime, 5 goroutines, channel buffer size is 3
             user     system      total        real
receive 14.702000   0.000000  14.702000 ( 14.668000)


jruby 1.6.7 (ruby-1.8.7-p357) (2012-02-22 3e82bc8) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_29) [darwin-x86_64-java]

150's prime, 5 goroutines, channel buffer size is 0
             user     system      total        real
receive  9.869000   0.000000   9.869000 (  9.836000)

150's prime, 5 goroutines, channel buffer size is 1
             user     system      total        real
receive 12.399000   0.000000  12.399000 ( 12.362000)

150's prime, 5 goroutines, channel buffer size is 2
             user     system      total        real
receive 13.146000   0.000000  13.146000 ( 13.154000)

150's prime, 5 goroutines, channel buffer size is 3
             user     system      total        real
receive 13.888000   0.000000  13.888000 ( 13.847000)


rubinius 1.2.4 (1.8.7 release 2011-07-05 JI) [x86_64-apple-darwin11.3.0]

150's prime, 5 goroutines, channel buffer size is 0
             user     system      total        real
receive 20.890472   3.099183  23.989655 ( 19.765032)

150's prime, 5 goroutines, channel buffer size is 1
             user     system      total        real
receive 21.727269   3.028753  24.756022 ( 20.554911)

150's prime, 5 goroutines, channel buffer size is 2
             user     system      total        real
receive 45.912357   5.814811  51.727168 ( 44.636344)

150's prime, 5 goroutines, channel buffer size is 3
             user     system      total        real
receive 46.211119   7.487593  53.698712 ( 44.716384)


rubinius 2.0.0dev (1.8.7 65c6146e yyyy-mm-dd JI) [x86_64-apple-darwin11.3.0]

150's prime, 5 goroutines, channel buffer size is 0
             user     system      total        real
receive 62.980970   4.578037  67.559007 ( 18.560938)

150's prime, 5 goroutines, channel buffer size is 1
             user     system      total        real
receive 52.822284   4.667321  57.489605 ( 15.986046)

150's prime, 5 goroutines, channel buffer size is 2
             user     system      total        real
receive 54.217875   4.579821  58.797696 ( 16.267339)

150's prime, 5 goroutines, channel buffer size is 3
             user     system      total        real
receive 59.092219   4.881411  63.973630 ( 17.664269)
