tokio::join 和不同的结果
tokio::join and different results
首先我编写了第一个实现,然后尝试将其简化为第二个,但令人惊讶的是第二个几乎慢了 3 倍。为什么?
第一次实施(更快):
let data: Vec<Arc<Data>> = vec![d1,d2,d3];
let mut handles = Vec::new();
for d in &data {
let d = d.clone();
handles.push(tokio::spawn(async move {
d.update().await;
}));
}
for handle in handles {
let _ = tokio::join!(handle);
}
第二次实施(较慢):
let data: Vec<Arc<Data>> = vec![d1,d2,d3];
for d in &data {
let d = d.clone();
let _ = tokio::join!(tokio::spawn(async move {
d.update().await;
}));
}
在第一个示例中,您将所有任务都派生到执行器上,允许它们并行 运行,然后按顺序加入所有任务。在第二个示例中,您按顺序将每个任务生成到执行器上,但您会等待该任务完成,然后再生成下一个任务,这意味着并行度为零,因此没有加速。同样,要注意的重要一点是,在第一个示例中,所有 任务都在后台取得进展,即使您正在等待它们一个接一个地完成。另外,join_all
之类的内容可能更适合第一个示例中的等待任务。
首先我编写了第一个实现,然后尝试将其简化为第二个,但令人惊讶的是第二个几乎慢了 3 倍。为什么?
第一次实施(更快):
let data: Vec<Arc<Data>> = vec![d1,d2,d3];
let mut handles = Vec::new();
for d in &data {
let d = d.clone();
handles.push(tokio::spawn(async move {
d.update().await;
}));
}
for handle in handles {
let _ = tokio::join!(handle);
}
第二次实施(较慢):
let data: Vec<Arc<Data>> = vec![d1,d2,d3];
for d in &data {
let d = d.clone();
let _ = tokio::join!(tokio::spawn(async move {
d.update().await;
}));
}
在第一个示例中,您将所有任务都派生到执行器上,允许它们并行 运行,然后按顺序加入所有任务。在第二个示例中,您按顺序将每个任务生成到执行器上,但您会等待该任务完成,然后再生成下一个任务,这意味着并行度为零,因此没有加速。同样,要注意的重要一点是,在第一个示例中,所有 任务都在后台取得进展,即使您正在等待它们一个接一个地完成。另外,join_all
之类的内容可能更适合第一个示例中的等待任务。