Open armanbilge opened 1 year ago
Explicitly cede-ing between expensive compute-bound operations is one of the strategies for addressing CPU-starvation and is suggested in the warning.
cede
https://github.com/typelevel/cats-effect/blob/832079aecbbf956fb18f11392cfeec6cdaa52915/core/shared/src/main/scala/cats/effect/CpuStarvationCheck.scala#L43-L44
How to do this is described in the scaladocs for cede.
https://github.com/typelevel/cats-effect/blob/52b5a3ba1623ff40fc48318c9a0bfae558f0e5ed/kernel/shared/src/main/scala/cats/effect/kernel/GenSpawn.scala#L263-L269
Implementing that correctly is not completely trivial (*cough* https://github.com/typelevel/cats-effect/pull/3166 😜) and noisy enough that it probably deserves its own combinator.
In fact I think we need a couple combinators, depending on whether or not the expensiveWork() is in F[_] or not.
expensiveWork()
F[_]
def cedeMap[A, B](fa: F[A])(f: A => B): F[B] = (fa <* cede).map(a => f(a)).guarantee(cede) def intercede[A](fa: F[A]): F[A] = cede *> fa.guarantee(cede)
(Names subject to bikeshed.) These should also be added as syntax and on IO itself.
IO
I think both variants are important, because for example the following would not achieve the desired semantics.
fa.flatMap(data => intercede(F.pure(expensiveWork(data))))
There, expensiveWork() would be computed eagerly when the pure(...) is constructed (before the cede), not when it is interpreted (after the cede).
pure(...)
I want to help resolve this issue. 😃
@biuld go for it!
Explicitly
cede
-ing between expensive compute-bound operations is one of the strategies for addressing CPU-starvation and is suggested in the warning.https://github.com/typelevel/cats-effect/blob/832079aecbbf956fb18f11392cfeec6cdaa52915/core/shared/src/main/scala/cats/effect/CpuStarvationCheck.scala#L43-L44
How to do this is described in the scaladocs for
cede
.https://github.com/typelevel/cats-effect/blob/52b5a3ba1623ff40fc48318c9a0bfae558f0e5ed/kernel/shared/src/main/scala/cats/effect/kernel/GenSpawn.scala#L263-L269
Implementing that correctly is not completely trivial (*cough* https://github.com/typelevel/cats-effect/pull/3166 😜) and noisy enough that it probably deserves its own combinator.
In fact I think we need a couple combinators, depending on whether or not the
expensiveWork()
is inF[_]
or not.(Names subject to bikeshed.) These should also be added as syntax and on
IO
itself.I think both variants are important, because for example the following would not achieve the desired semantics.
There,
expensiveWork()
would be computed eagerly when thepure(...)
is constructed (before thecede
), not when it is interpreted (after thecede
).