-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Add a yield primitive for computation-heavy tasks #592
Comments
This sounds like an interesting idea! Just thinking it through, we can obviously write a macro for this, and I think it could be as simple as:
That's obviously not syntactically accurate, but, I think it would work? Random thoughts:
|
And, just in case others stumble on to this: this would clearly not be a true coroutine with stack resumption, and all of that. A future would still need to maintain state, but as long as it did that, it could co-operatively yield itself to the runtime. |
Hmm, I'm not sure about the possibility to return directly With Though, thinking of it… maybe that's actually something that should be implemented in |
From a pure coroutine perspective, yeah, this wouldn't be (easily) possible. I do think there's a valuable, and approachable, technical outcome from your original problem state, though. A future is just a normal type that implements the I can totally imagine a future with a list of work items, and every time it |
Also, regarding your comment about only returning |
Oh yeah, so I was thinking about the conditional yield as being in a more coroutine-like fashion within async/await, hence the need to yield once and then not yield (in order to actually execute the code that comes after). I guess these are two different designs, mine being like |
Yeah, I think I see what you mean now. I'm certainly not the dictator of design vision in Tokio, but I do think this would be an interesting tool to have in the toolbox, so to speak. Could be useful in situations where you're doing heavy work, but aren't looking to actually run an entirely separate thread pool, etc. Up to you whether you want to close it or not. I think it'd be great to flesh out an example of the thing, one way or another, to build a more meaningful discussion. |
Leaving open to track the idea, then :) |
Both are useful. The macro is useful when implementing futures by hand. And yes, one would have to track extra state. For await! Having a future variant also does seem useful. The question where should these two helpers live and how should they be differentiated. |
|
https://tokio.rs/docs/getting-started/tasks/ mentions “Tasks must not perform computation heavy logic or they will prevent other tasks from executing.”
However, sometimes heavy computation must be performed for a task (to take the example from said web page, a server that returns the n-th fibonacci sequence number). Spawning a new thread for each such request wouldn't be efficient, and handling a separate thread pool of workers wouldn't be simple.
So I think maybe a primitive like
yield!()
, that would returnPending
and immediately re-enqueue the future for further progress, might make sense: it could be called at times during the computation-intensive task, so that other tasks aren't blocked from progress. Obviously it requires that the executor be fair for this to work, ie. a yield-ed task should be enqueued at the end of the to-be-run task queue, not at the beginning.What do you think about this?
The text was updated successfully, but these errors were encountered: