原本作了一个并发抓取,觉得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