-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Provide a blocking pool for all runtimes #588
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
Comments
Some observations on There needs to be some way to retrieve a return value for the blocking operation closure when it completes. For example in tokio-fs, the /// Dispatch a blocking operation in the closure to a non-reactor thread, and
/// return a future representing its return value.
pub fn dispatch_blocking<T>(f: Box<dyn FnOnce() -> T + Send>)
-> DispatchBlocking<T>
where T: Send + 'static; In an
Thus, while I do think the I have some other thoughts on interface with |
@dekellum The re: the semaphore, my thought is just that limiting concurrency would be left to a higher level API and not be a concern of |
I have a proof of concept implementation focused on the api/safety/ergonomics, so far out of tree, here: https://github.com/dekellum/blocking-permit/blob/master/src/lib.rs Please take a look. To summarize briefly, this culminates not surprisingly in a permit_or_dispatch!(|| { /*.. blocking code..*/ });
permit_or_dispatch!(&semaphore, || { /*.. blocking code..*/ }); Helper macro for use in the context of an If the first argument is a If all usage is via this macro, then arranging internal to the macro, the oneshot for return from Any parts of this you think might work as PR(s) to Tokio? Also I don't have a great sence of how to organize this with regard to current/future tokio crate boundaries, so could use some suggestions there. |
I made several improvements on my PoC master branch. |
Provides a thread pool dedicated to running blocking operations (#588) and update `tokio-fs` to use this pool. In an effort to make incremental progress, this is an initial step towards a final solution. First, it provides a very basic pool implementation with the intend that the pool will be replaced before the final release. Second, it updates `tokio-fs` to always use this blocking pool instead of conditionally using `threadpool::blocking`. Issue #588 contains additional discussion around potential improvements to the "blocking for all" strategy. The implementation provided here builds on work started in #954 and continued in #1045. The general idea is th same as #1045, but the PR improves on some of the details: * The number of explicit operations tracked by `File` is reduced only to the ones that could interact. All other ops are spawned on the blocking pool without being tracked by the `File` instance. * The `seek` implementation is not backed by a trait and `poll_seek` function. This avoids the question of how to model non-blocking seeks on top of a blocking file. In this patch, `seek` is represented as an `async fn`. If the associated future is dropped before the caller observes the return value, we make no effort to define the state in which the file ends up.
Provides a thread pool dedicated to running blocking operations (#588) and update `tokio-fs` to use this pool. In an effort to make incremental progress, this is an initial step towards a final solution. First, it provides a very basic pool implementation with the intend that the pool will be replaced before the final release. Second, it updates `tokio-fs` to always use this blocking pool instead of conditionally using `threadpool::blocking`. Issue #588 contains additional discussion around potential improvements to the "blocking for all" strategy. The implementation provided here builds on work started in #954 and continued in #1045. The general idea is th same as #1045, but the PR improves on some of the details: * The number of explicit operations tracked by `File` is reduced only to the ones that could interact. All other ops are spawned on the blocking pool without being tracked by the `File` instance. * The `seek` implementation is not backed by a trait and `poll_seek` function. This avoids the question of how to model non-blocking seeks on top of a blocking file. In this patch, `seek` is represented as an `async fn`. If the associated future is dropped before the caller observes the return value, we make no effort to define the state in which the file ends up.
In a similar incremental approach as your #1495, @carllerche, I'd like to make progress on the "blocking for all" goal (as in all runtimes and all types of "blocking" operations): The pub fn enter_blocking_section() -> Result<(), BlockingError> {}
pub fn exit_blocking_section() -> Result<(), BlockingError> {} …with the existing |
On master. |
Continuation of this topic, here: http://gravitext.com/2020/01/13/blocking-permit.html |
Uh oh!
There was an error while loading. Please reload this page.
Currently, tokio-threadpool provides a
blocking
API (#317) that enables tasks to perform operations that would block the current thread.This API only works with the concurrent Runtime, which means that the
current_thread::Runtime
is unable to perform blocking operations and use tokio-fs.There should be a blocking pool strategy that is usable from all runtimes.
This strategy should avoid unbounded buffering problems that a traditional threadpool + queue strategy would have.
At a high level, there would most likely be some new functions added to the
Executor
trait intokio_executor
. One would could take aBox<FnOnce()>
that contains a blocking operation:This function would be sent to a threadpool to run. This function would also be unbounded. Then, we could use a Semaphore to limit concurrent blocking ops. I'm not sure what the best way to expose this would be yet... but we could start by encapsulating it in each library. For example, there would be a tokio-fs limit and that lib would be responsible for storing the semaphore somewhere.
There still needs to be a way to perform the "fast block" strategy that tokio-threadpool uses. This may need another function on
Executor
:The logic for blocking would be to first, try to enter a blocking section. If that fails, dispatch an op to
dispatch_blocking
.Rel: #432
The text was updated successfully, but these errors were encountered: