標籤:
本來做了一個並發抓取,以為Ruby1.9以後添加的Fiber是類似於golang那種,可以實現並發運行,可是發現效率沒有提高,為了確認Fiber是不是在並發執行,於是我做了一個這樣的測試代碼。
首先搞一個php檔案:
<?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)
time for i in {1..5}; do (curl localhost/test.php?i=$i) & if [ "$i" -eq "5" ]; then wait; fi ; donetime 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秒左右,證明這完全是一個一個在跑的。
#!/usr/bin/env rubyrequire ‘open-uri‘;fib = Fiber.new do (1..5).each do |i| Fiber.yield open("http://localhost/test.php?i=#{i}").read endendFiber.new do 5.times do puts fib.resume endend.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,只不過是把任務一個一個壓棧,然後在一個一個等待著他們運行完畢,完全不能自由調度,真沒見到有什麼實質用處。
比如 這裡 http://www.infoq.com/cn/news/2007/09/ruby-1-9-fibers
標題就是 :Ruby 1.9加入纖程實現輕量級並發 ,直接就是在誤導新手啊.
Ruby的Fiber根本不是用來做並發的~