异步Rust中的多线程-为什么我的代码无法并行化?

我试图通过运行以下函数来有意耗尽 API 限制(900 次调用):

#[get("/exhaust")]
pub async fn exhaust(_pool: web::Data<PgPool>, config: web::Data<Arc<Settings>>) -> impl Responder {
    let mut handles = vec![];

    for i in 1..900 {
        let inner_config = config.clone();
        let handle = thread::spawn(move || async move {
            println!("running thread {}", i);
            get_single_tweet(inner_config.as_ref().deref(), "1401287393228038149")
                .await
                .unwrap();
        });
        handles.push(handle);
    }

    for h in handles {
        h.join().unwrap().await;
    }

    HttpResponse::Ok()

我的机器有 16 个内核,所以我希望上面的运行速度比单线程函数快 16 倍,但事实并非如此。事实上,它的运行速度与单线程版本一样慢。

这是为什么?我错过了什么?

注意:这move || async move部分对我来说看起来有点奇怪,但我是按照编译器的建议到达那里的。由于async closures being unstable. 这可能是问题吗?

回答

此代码确实会async同步运行您的块。一个async块创建了一个实现 的类型Future,但要知道的一件事是Futures 不会自己开始运行,它们必须被await-ed 或提供给执行程序才能运行。

thread::spawn使用返回 a 的闭包调用Future不会执行它们;线程只是创建async块并返回。所以这些async块实际上并没有被执行,直到你await在循环中它们才会被执行handles,这将按顺序处理期货。

解决此问题的一种方法是join_allfutures板条箱中同时运行它们。

let mut futs = vec![];

for i in 1..900 {
    let inner_config = config.clone();
    futs.push(async move {
        println!("running thread {}", i);
        get_single_tweet(inner_config.as_ref().deref(), "1401287393228038149")
            .await
            .unwrap();
    });
}

futures::future::join_all(futs).await;


以上是异步Rust中的多线程-为什么我的代码无法并行化?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>