concurrency - 在没有 IO 的光纤之间循环

标签 concurrency parallel-processing crystal-lang kemal

据我所知, Crystal 用 io 循环光纤,这意味着如果一根光纤在等待 io, Crystal 将切换到另一根光纤。

如果我们生成两条纤维,但其中之一在没有 io 的情况下进行恒定计算/循环会怎样?

例如,使用下面的代码服务器不响应任何 http 请求

spawn do
  Kemal.run
end

spawn do
  # constant computation/loop with no IO
  some_func
end

Fiber.yield
# or sleep

最佳答案

默认情况下,Crystal 使用协作式多任务处理。为了实现它,Crystal 运行时提供了 Fibers .由于它们的合作性质,您必须不时让步执行(例如使用 Fibers.yield ):

Fibers are cooperative. That means execution can only be drawn from a fiber when it offers it. It can't be interrupted in its execution at random. In order to make concurrency work, fibers must make sure to occasionally provide hooks for the scheduler to swap in other fibers. [...]

When a computation-intensive task has none or only rare IO operations, a fiber should explicitly offer to yield execution from time to time using Fiber.yield to break up tight loops. The frequency of this call depends on the application and concurrency model.


请注意,CPU 密集型操作并不是其他 Fiber 饥饿的唯一来源。当调用可能阻塞的 C 库时,Fiber 也会等待操作完成。一个例子是长轮询操作,它将等待下一个事件或最终超时(例如 Kafka 中的 rd_kafka_poll)。为了防止这种情况,最好使用异步 API 版本(如果可用),或使用较短的轮询间隔(例如 0 表示 Kafka 轮询)并将 sleep 操作转移到 Crystal 运行时,以便其他 Fiber 可以运行。
2019年晶晶推出support for parallelism .通过运行多个工作线程,您还可以防止一次昂贵的计算使所有其他操作都处于饥饿状态。但是,您必须小心,因为程序的响应性(甚至可能是正确性)可能取决于工作人员的数量(例如,只有一名工作人员,它仍然会挂起)。总体而言,即使您最终使用多个 worker 来提高多核机器上的性能,偶尔在耗时的操作中让步似乎是更好的解决方案。

关于concurrency - 在没有 IO 的光纤之间循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53712967/

相关文章:

java - 多少线程安全是太多了?

Spring Batch - 并行运行多个作业

java - 如何减少java并发模式失败和过多gc

java - 如何在给定执行时间的情况下每隔固定时间调用方法

java - 可以从一个线程转移到另一个线程的锁

c++ - MPI 计算在多核上比在单核上错误

parallel-processing - Omp 部分与 Omp 工作共享

crystal-lang - Crystal 通过引用或值传递变量

xpath - Crystal XPath库或实现