最近重讀了《Programming Lua》,對協(xié)程做了重點復(fù)習(xí)。眾所周知,Ruby1.9引入了Fiber,同樣是coroutine,不過Ruby Fiber支持全對稱協(xié)程(通過fiber庫),而Lua只支持所謂半對稱協(xié)程。
??? 這里將對Lua、LuaJIT和Ruby Fiber的切換效率做個對比測試,測試場景很簡單:兩個coroutine相互切換達到5000萬次,統(tǒng)計每秒切換的次數(shù),各測試多次取最佳。
??? lua的程序如下:
???
c1=coroutine.create(function?()
?????????????????????while?true?do
???????????????????????coroutine.yield()
?????????????????????end
????????????????????end)
c2=coroutine.create(function?()
?????????????????????while?true?do
???????????????????????coroutine.yield()
?????????????????????end
????????????????????end)
local?start=os.clock()
local?count=50000000
for?i=1,count?do
?coroutine.resume(c1)
?coroutine.resume(c2)
end
print(4*count/(os.clock()-start))
??? 考慮到在循環(huán)中事實上發(fā)生了四次切換:main->c1,c1->main,main->c2,c2->main,因此乘以4。
???
Ruby Fiber的測試分兩種,采用transfer的例程如下:
require?'fiber'
require?'benchmark'
Benchmark.bm?do?|x|
??MAX_COUNT=50000000
??f1=Fiber.new?do?|other,count|
?????while?count<MAX_COUNT
??????other,count=other.transfer(Fiber.current,count.succ)
?????end
??end
??f2=Fiber.new?do?|other,count|
????while?count<MAX_COUNT
??????other,count=other.transfer(Fiber.current,count.succ)
????end
??end
??x.report{
????f1.resume(f2,0)
??}
end
????
Ruby Fiber采用resume/yield的例程如下:
require?'benchmark'
f1=Fiber.new?do
??while?true
????Fiber.yield
??end
end
f2=Fiber.new?do
??while?true
????Fiber.yield
??end
end
COUNT=50000000
Benchmark.bm?do?|x|
??x.report{
?????COUNT.times?do
?????????f1.resume
?????????f2.resume
?????end
??}
end
???? 測試環(huán)境:
????????? CPU :??? Intel(R) Core(TM)2 Duo CPU???? P8600? @ 2.40GHz
????????? Memory:? 3GB
????????? System :? Linux dennis-laptop 2.6.31-14-generic #48-Ubuntu SMP
????????? Lua??? : 5.1.4
?????????
ruby? :? 1.9.1p378
????????? LuaJIT:? 1.1.5和2.0.0-beta2
????? 測試結(jié)果如下:
????
? | ?Lua | ?LuaJIT 1.1.5
| ?LuaJIT 2.0.0-beta2
| ?ruby-transfer
| ?ruby-resume/yield |
?次數(shù) | ?6123698 | ?9354536 | ?24875620 | ?825491 | ?969649 |
????? 結(jié)論:
????? 1、lua的協(xié)程切換效率都是百萬級別,luaJIT 2.0的性能更是牛叉,切換效率是原生lua的4倍,達到千萬級別。
????? 2、相形之下,Ruby Fiber的效率比較差了,十萬級別。
????? 3、Ruby使用transfer的效率比之resume/yield略差那么一點,排除一些測試誤差,兩者應(yīng)該是差不多的,從ruby源碼上看resume/yield和transfer的調(diào)用是一樣的,resume還多了幾條指令。
????? 4、額外信息,Ruby Fiber和lua coroutine都只能跑在一個cpu上,這個測試肯定能跑滿一個cpu,內(nèi)存占用上,lua也比ruby小很多。
?