RubyでErlangっぽいプロセスあれこれ

いろいろ実装方法があるみたいで___φ( ̄^ ̄ )メモメモ


jijixi's diary - あー……あかん、あかんわ…… , 『クロージャによる超軽量並行プロセス』を Ruby で , 思い切って Safari 3 Beta を入れてみた ,..


O'camlの実装をRubyに置き換えたものらしいですが、
う〜ん。いまいちわかんないですね。もう一寸読んでみます。


404 Blog Not Found:ruby & perl - 軽量プロセスをthreadで代用


なるほど、QueueとThreadで同様なことができるんですか。
こちらは、簡単な実装ですし分かりやすかったのでコピッてRubyっぽくしてみました。
しかし関数内部で関数定義できたんだ。知らなかった*w*


ついでなのでJRubyとCRubyで動かしてみました。


両方で動かしてみると結構JRubyも早いんですね^^;
それでもってネイティブな分Threadの性能が高いのかな?

DualCPU*1じゃないので恩恵に預かれてませんが、マルチコアだとどれくらい性能出るんでしょうね。



require 'thread'

def fib(n)
n < 2 ? 1 : fib(n - 2) + fib(n - 1)
end

def timeit
def now
t = Time.now
t.tv_sec + t.tv_usec.to_f / 1e6
end
started = now
yield
now - started
end

def worker(n, q)
Thread.new{ q.push("fib(#{n}) = #{fib(n)}") }
end

def manager(n, q)
Thread.new{ n.times{puts q.shift} }
end

nums = (1..28).to_a
elapsed = timeit{
q = Queue.new
t = manager(nums.length, q)
nums.reverse.each{|x| worker(x, q) }
t.join
}

puts "Thread #{elapsed} seconds."

def work(n)
"fib(#{n}) = #{fib(n)}"
end

elapsed = timeit{
nums.reverse.each{ |x| puts work(x) }
}

puts "Sync #{elapsed} seconds."


JRubyアウトプット


fib(9) = 55
fib(10) = 89
fib(11) = 144
fib(13) = 377
fib(14) = 610
fib(12) = 233
fib(15) = 987
fib(21) = 17711
fib(22) = 28657
fib(16) = 1597
fib(18) = 4181
fib(17) = 2584
fib(1) = 1
fib(2) = 2
fib(3) = 3
fib(4) = 5
fib(5) = 8
fib(6) = 13
fib(7) = 21
fib(8) = 34
fib(19) = 6765
fib(20) = 10946
fib(23) = 46368
fib(24) = 75025
fib(25) = 121393
fib(26) = 196418
fib(27) = 317811
fib(28) = 514229
Thread 3.1559998989105225 seconds.
fib(28) = 514229
fib(27) = 317811
fib(26) = 196418
fib(25) = 121393
fib(24) = 75025
fib(23) = 46368
fib(22) = 28657
fib(21) = 17711
fib(20) = 10946
fib(19) = 6765
fib(18) = 4181
fib(17) = 2584
fib(16) = 1597
fib(15) = 987
fib(14) = 610
fib(13) = 377
fib(12) = 233
fib(11) = 144
fib(10) = 89
fib(9) = 55
fib(8) = 34
fib(7) = 21
fib(6) = 13
fib(5) = 8
fib(4) = 5
fib(3) = 3
fib(2) = 2
fib(1) = 1
Sync 3.0470001697540283 seconds.

CRubyアウトプット


fib(9) = 55
fib(11) = 144
fib(6) = 13
fib(7) = 21
fib(8) = 34
fib(10) = 89
fib(5) = 8
fib(3) = 3
fib(4) = 5
fib(12) = 233
fib(2) = 2
fib(13) = 377
fib(1) = 1
fib(14) = 610
fib(15) = 987
fib(16) = 1597
fib(17) = 2584
fib(18) = 4181
fib(19) = 6765
fib(20) = 10946
fib(21) = 17711
fib(22) = 28657
fib(23) = 46368
fib(24) = 75025
fib(25) = 121393
fib(26) = 196418
fib(27) = 317811
fib(28) = 514229
Thread 5.96900010108948 seconds.
fib(28) = 514229
fib(27) = 317811
fib(26) = 196418
fib(25) = 121393
fib(24) = 75025
fib(23) = 46368
fib(22) = 28657
fib(21) = 17711
fib(20) = 10946
fib(19) = 6765
fib(18) = 4181
fib(17) = 2584
fib(16) = 1597
fib(15) = 987
fib(14) = 610
fib(13) = 377
fib(12) = 233
fib(11) = 144
fib(10) = 89
fib(9) = 55
fib(8) = 34
fib(7) = 21
fib(6) = 13
fib(5) = 8
fib(4) = 5
fib(3) = 3
fib(2) = 2
fib(1) = 1
Sync 2.90599989891052 seconds.

*1:重い処理をさせてみると、CRubyが結構早いです。あとJRubyはメモリ関係の設定がメンドクサイ。同じプログラムでJRubyだとメモリ例外が出る事も。まあ当たり前ですが、JRubyJavaと組み合わせてナンボですね^^