Files
core/test/rust/performance/task/shared.rs
T
2026-11-03 03:32:07 +00:00

118 lines
4.6 KiB
Rust

// 手写 Rust 与 Dever 生成代码使用同一个运行时,隔离生成代码与运行时策略的成本。
// 原始直接 Tokio 参照继续保留;这里不调用任何生成函数或填充错误布局。
use dever_runtime::task::Scope;
async fn handwritten_pair(scope: &Scope<'_>, values: &[i64]) -> Result<i64, NativeAsyncFailure> {
let first_values = values.to_vec();
let first = scope
.spawn_leaf(move || native_async_total(first_values, false))
.map_err(|error| NativeAsyncFailure::Fault(task_fault(error)))?;
let second_values = values.to_vec();
let second = match scope.spawn_leaf(move || native_async_total(second_values, false)) {
Ok(task) => task,
Err(error) => {
first.cancel();
let _ = first.wait().await;
return Err(task_fault(error).into());
}
};
let first = first.wait().await
.map_err(|error| NativeAsyncFailure::Fault(task_fault(error)))
.and_then(|result| result);
if first.is_err() { second.cancel(); }
let second = second.wait().await
.map_err(|error| NativeAsyncFailure::Fault(task_fault(error)))
.and_then(|result| result);
first?.checked_add(second?)
.ok_or_else(|| task_fault("integer overflow").into())
}
async fn handwritten_cancel(scope: &Scope<'_>) -> Result<i64, NativeAsyncFailure> {
let task = scope.spawn_leaf(|| native_fallible_sleep(60000))
.map_err(|error| NativeAsyncFailure::Fault(task_fault(error)))?;
if let Some(result) = task.stop().await
.map_err(|error| NativeAsyncFailure::Fault(task_fault(error)))? {
result?;
}
Ok(1)
}
fn shared_async(values: &[TaskCase]) -> Result<i64, Fault> {
let Some(value) = values.first() else { return Ok(0); };
value.generated.run(async |scope| handwritten_pair(scope, &value.values).await)
.map_err(task_fault)?.map_err(Into::into)
}
fn shared_cancel(values: &[TaskCase]) -> Result<i64, Fault> {
let Some(value) = values.first() else { return Ok(0); };
value.generated.run(async |scope| handwritten_cancel(scope).await)
.map_err(task_fault)?.map_err(Into::into)
}
fn shared_worker<const SLEEP: bool>(values: &[TaskCase]) -> Result<i64, Fault> {
let Some(value) = values.first() else { return Ok(0); };
value.generated.run(async |scope| {
let owned = value.values.clone();
scope.blocking(move || {
if SLEEP {
std::time::Instant::now()
.checked_add(std::time::Duration::ZERO)
.ok_or_else(|| task_fault("sleep deadline"))?;
std::thread::sleep(std::time::Duration::ZERO);
}
native_total(&owned)
}).await.map_err(task_fault)?
}).map_err(task_fault)?
}
// 两侧都在真实父任务中执行双子任务;同样复制输入,不改用更大的错误或状态。
fn nested<Work>(
values: &[TaskCase],
call: impl FnOnce(Scope<'static>, Vec<i64>) -> Work + Send + 'static,
) -> Result<i64, Fault>
where
Work: std::future::Future<Output = Result<i64, Fault>> + Send + 'static,
{
let Some(value) = values.first() else { return Ok(0); };
let owned = value.values.clone();
value.generated.run(async move |scope| {
let parent = scope.spawn(move |child| call(child, owned)).map_err(task_fault)?;
parent.wait().await.map_err(task_fault)?
}).map_err(task_fault)?
}
fn generated_nested(values: &[TaskCase]) -> Result<i64, Fault> {
nested(values, |scope, owned| async move {
GENERATED_ASYNC(&owned, &scope).await.map_err(task_fault)
})
}
fn reference_nested(values: &[TaskCase]) -> Result<i64, Fault> {
nested(values, |scope, owned| async move {
handwritten_pair(&scope, &owned).await.map_err(Into::into)
})
}
fn shared_runtime(cases: &[TaskCase]) {
compare_named(
"task_parallel_shared_runtime", cases, 500,
generated_parallel, shared_worker::<false>, |value| *value as u64, "rust_runtime",
);
compare_named(
"task_blocking_shared_runtime", cases, 500,
generated_blocking, shared_worker::<true>, |value| *value as u64, "rust_runtime",
);
compare_named(
"task_async_shared_runtime", cases, 1000,
generated_async, shared_async, |value| *value as u64, "rust_runtime",
);
compare_named(
"task_cancel_shared_runtime", cases, 1000,
generated_cancel, shared_cancel, |value| *value as u64, "rust_runtime",
);
compare_named(
"task_nested_shared_runtime", cases, 1000,
generated_nested, reference_nested, |value| *value as u64, "rust_runtime",
);
}