我在同步方法内调用了异步代码(此方法是特征的一部分,我无法异步实现它),因此我使用 block_on
来等待异步调用完成。
同步方法将从异步代码中调用。
因此,应用程序位于 #[tokio::main]
中,当发生某些事件(端点命中)时,它会调用同步方法,同步方法将调用一些异步代码并等待它完成并返回。
事实证明 block_on
不能在异步代码中使用。我发现 tokio::task::block_in_place 会在异步上下文中生成同步上下文,从而允许在其中调用 block_on 。
所以该方法现在看起来像这样:
impl SomeTrait for MyStruct {
fn some_sync_method(&self, handle: tokio::runtime::Handle) -> u32 {
tokio::task::block_in_place(|| {
handle.block_on(some_async_function())
}
}
}
此实现更好还是使用 futures::executor::block_on
代替:
impl SomeTrait for MyStruct {
fn some_sync_method(&self, handle: tokio::runtime::Handle) -> u32 {
futures::executor::block_on(some_async_function())
}
}
这两种实现之间的根本区别是什么?在什么情况下它们各自会更有效。
顺便说一句,这个方法被多次调用。这是网络服务器的一部分。
最佳答案
不要使用futures::executors::block_on()
。即使在比较性能之前,还有一些更重要的事情需要考虑:futures::executors::block_on()
在这里是错误的,因为它会阻塞异步运行时。
As explained in block_in_place()
docs :
In general, issuing a blocking call or performing a lot of compute in a future without yielding is problematic, as it may prevent the executor from driving other tasks forward. Calling this function informs the executor that the currently executing task is about to block the thread, so the executor is able to hand off any other tasks it has to a new worker thread before that happens. See the CPU-bound tasks and blocking code section for more information.
futures::executors::block_on()
可能会性能更高一些(虽然我没有进行基准测试),因为它不会通知执行程序。但这就是重点:您需要通知执行人。否则,您的代码可能会陷入困境,直到您的阻塞函数完成为止,基本上是串行执行的,而不利用设备的资源。
如果此代码是大部分代码,您可以重新考虑使用异步运行时。如果您只生成线程,可能会更有效。或者干脆放弃使用该库并仅使用异步代码。
关于rust - futures::executor::block_on 和 block_in_place 之间是否存在性能差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73269315/