118 lines
4.6 KiB
Rust
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",
|
|
);
|
|
}
|