Ogu*_*gic 5 parallel-processing concurrency crystal-lang kemal
据我所知,水晶会通过 io 循环光纤,这意味着如果一根光纤正在等待 io,水晶将切换到另一根光纤。
如果我们生成两个纤程,但其中一个在没有 io 的情况下进行持续计算/循环,该怎么办?
例如,使用下面的代码,服务器不会响应任何 http 请求
spawn do
Kemal.run
end
spawn do
# constant computation/loop with no IO
some_func
end
Fiber.yield
# or sleep
Run Code Online (Sandbox Code Playgroud)
默认情况下,Crystal 使用协作式多任务处理。为了实现它,Crystal 运行时提供了Fibers。由于它们的合作性质,您必须不时地让出执行(例如使用Fibers.yield):
纤维是合作的。这意味着只有在纤程提供执行时才能从纤程中提取执行。它的执行不能被随机中断。为了使并发工作,纤程必须确保偶尔为调度程序提供钩子以交换其他纤程。[...]
当计算密集型任务没有或只有很少的 IO 操作时,纤程应该使用 Fiber.yield 显式地提供时不时的屈服执行,以打破紧密的循环。此调用的频率取决于应用程序和并发模型。
请注意,CPU 密集型操作并不是导致其他光纤饥饿的唯一原因。当调用可能阻塞的C库时,Fiber也会等待操作完成。一个例子是长轮询操作,它将等待下一个事件或最终超时(例如Kafka 中的rd_kafka_poll)。为了防止这种情况,最好选择异步 API 版本(如果可用),或者使用较短的轮询间隔(例如 Kafka 轮询为 0)并将睡眠操作转移到 Crystal 运行时,以便其他 Fiber 可以运行。
2019 年,Crystal 引入了对并行性的支持。通过运行多个工作线程,您还可以防止一项昂贵的计算导致所有其他操作挨饿。但是,您必须小心,因为程序的响应能力(甚至可能是正确性)可能取决于工作人员的数量(例如,只有一名工作人员,它仍然会挂起)。总体而言,即使您最终使用多个工作线程来提高多核机器上的性能,在耗时的操作中偶尔进行屈服似乎是更好的解决方案。
| 归档时间: |
|
| 查看次数: |
283 次 |
| 最近记录: |