Nếu bạn muốn榨取最多性能出于你的Ruby项目,我们必须探索fibers和它们如何工作。
让我们从一个简单的问题开始…
纤维是什么?
纤维是工作者,它们运行代码并跟踪自己的进度。换句话说,纤维是并发机制。
是的!
就像线程。区别在于你对纤维的控制比线程多。
在什么意义上你有更多控制?
好吧。
你的操作系统决定何时运行线程 & 何时暂停它们。
纤维不是这种情况!
你必须准确告诉纤维何时运行 & 何时停止。
纤维 vs 线程
线程感觉像在后台运行,做它们的事。
纤维不这样做。
当纤维运行时,它成为主程序直到你停止它。
让我们看代码示例!
使用纤维:示例
用Fiber.new和block创建纤维。
示例:
f = Fiber.new { puts 1 }
然后用resume方法运行纤维。
像这样:
f.resume
这打印1并把控制权返回主程序。
但怎么停止纤维?
用Fiber.yield方法,这不同于用于block的yield关键字。
示例:
f = Fiber.new { puts 1; Fiber.yield; puts 2 }
f.resume # 1
f.resume # 2
这将在用resume启动纤维后打印1,然后停止。
如果你再次调用resume…
它将从离开的地方继续并打印2。
注意: 再次恢复此纤维导致
FiberError: dead fiber called,因为没有更多代码可运行。
这就是为什么纤维有用!
在纤维内部调用Fiber.yield就像按暂停键。允许你在循环中间或你写在纤维block中的任何代码处停止。
纤维 & 循环:无限序列
我们可以用这个„暂停键“效果创建无限序列。
成分:
- 纤维
- 循环
- 计数器
例如,阶乘数:
factorial = Fiber.new do count = 1 loop do Fiber.yield (1..count).inject(:*) count += 1 end end
你可以按需要多次用resume方法使用此纤维,获取序列中的下一个数字。
示例:
Array.new(5) { factorial.resume } # [1, 2, 6, 24, 120]
不错!
纤维 & IO:异步操作
纤维对必须等待的事情(如网络连接)比线程更快 & 更高效。
为什么?
因为纤维导致更少上下文切换。
上下文切换是CPU从当前任务变到另一个任务。
这有小成本,但累积起来!
我用Linux的perf工具做了一些测试,发现在简单Ruby应用中,纤维产生的上下文切换比线程少3倍。
听起来不错?
你现在就可以开始用纤维:
- 用
IO.select方法 + Reactor设计模式 - 用async gem
- 用falcon应用服务器
记住…
没有灵丹妙药,但值得测试 & 看纤维能为你做什么 🙂
总结
你已学会Ruby中的纤维!纤维允许你创建可按你意愿暂停 & 恢复的代码单元。
现在轮到你试试了。
谢谢阅读!