Ruby的Fiber根本不是用來作併發的~

原本作了一個併發抓取,覺得Ruby1.9之後添加的Fiber是相似於golang那種,能夠實現併發運行,但是發現效率沒有提升,爲了確認Fiber是否是在併發執行,因而我作了一個這樣的測試代碼。php

首先搞一個php文件:node

<?php
$i = intval(isset($_GET['i']) ? $_GET['i'] : (!empty($argv[1]) ? $argv[1] : 0));

if($i>0){
    sleep(5-$i);
}
echo $i, "\n";

而後用命令行測試,確認這個php文件是不會block的(由於沒有session鎖,應該不會block)golang

time for i in {1..5}; do (curl localhost/test.php?i=$i) & if [ "$i" -eq "5" ]; then wait; fi ; done
time for i in {1..5}; do (php test.php $i) & if [ "$i" -eq "5" ]; then wait; fi ; done

這裏兩種方式運行時間都是4秒左右,證實,是能夠並行運行。  real    0m4.019s
而後用fiber執行: real    0m10.086s  10秒左右,證實這徹底是一個一個在跑的。
shell

#!/usr/bin/env ruby

require 'open-uri';
fib = Fiber.new do
    (1..5).each do |i|
        Fiber.yield open("http://localhost/test.php?i=#{i}").read
    end
end

Fiber.new do
    5.times do
        puts fib.resume
    end
end.resume

結果測試發現根本不能實現併發,並且是一個一個在跑,跑完一個跑下一個,因此別在被誤解了Fiber根本不能併發執行,並且還有一個更奇葩的,若是是5個Fiber.yield,在resume的時候卻能夠調用6次resume,這個設計真不怎麼樣。

後來我在 stackoverflow上找到這個 http://stackoverflow.com/questions/3066392/can-ruby-fibers-be-concurrent 
看第二個回答,大概是說,Fiber只是一種 control-flow 結構,並非用來搞併發的,他們不能併發運行,只能算是一種 Coroutine ,和並行執行不是一種東西,在ruby裏,惟一能實現併發的是 Thread,那麼我就奇怪爲什麼網上有那麼多人宣稱能夠用 Fiber 來實現併發運行?併發和協程但是不同的。編程

不過也能夠這樣來講,Fiber是能夠實現 concurrency,這個 concurrency 並非 Parallelism,就是說,能夠實現所謂的併發,可是內部倒是一個一個運行的,並且並不會由於IO阻塞的時候自動調度,你須要手動調度,實際性能沒有任何提高,用了只會增長代碼邏輯複雜度,絲絕不能帶來任何益處,一樣是concurrency,golang、nodejs均可以在IO阻塞時候自動調度,因此能實現正真意義上的併發編程,但Fiber,只不過是把任務一個一個壓棧,而後在一個一個等待着他們運行完畢,徹底不能自由調度,真沒見到有什麼實質用處。ruby

好比 這裏 http://www.infoq.com/cn/news/2007/09/ruby-1-9-fibers   
標題就是 :Ruby 1.9加入纖程實現輕量級併發 ,直接就是在誤導新手啊.session

相關文章
相關標籤/搜索