Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"cedeMap" and "intercede" combinators #3318

Open
armanbilge opened this issue Dec 19, 2022 · 2 comments · May be fixed by #3353
Open

"cedeMap" and "intercede" combinators #3318

armanbilge opened this issue Dec 19, 2022 · 2 comments · May be fixed by #3353

Comments

@armanbilge
Copy link
Member

armanbilge commented Dec 19, 2022

Explicitly cede-ing between expensive compute-bound operations is one of the strategies for addressing CPU-starvation and is suggested in the warning.

"""[WARNING] Your CPU is probably starving. Consider increasing the granularity
|of your delays or adding more cedes. This may also be a sign that you are

How to do this is described in the scaladocs for cede.

* The danger is that these types of long-running actions outside of the monadic context can
* result in degraded fairness properties. The solution is to add an explicit `cede` both
* before and after the expensive operation:
*
* {{{
* (fa <* F.cede).map(data => expensiveWork(data)).guarantee(F.cede)
* }}}

Implementing that correctly is not completely trivial (*cough* #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.

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.

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).

@biuld
Copy link

biuld commented Jan 8, 2023

I want to help resolve this issue. 😃

@armanbilge
Copy link
Member Author

@biuld go for it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
3 participants