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

226 lines
6.2 KiB
Rust

// 调度器保持存活,计时包含输入复制、提交、结果领取和作用域清理。
// 独立参照针对同样的一层双任务/worker/计时器,不能代表任意嵌套并发已验收。
use dever_runtime::task::{Limits, Runtime};
struct TaskCase {
generated: Runtime,
native: NativeTasks,
values: Vec<i64>,
}
fn new_runtime() -> Runtime {
Runtime::new(Limits {
threads: 2,
workers: 2,
tasks: 8,
})
.unwrap()
}
fn generated_sync(values: &[TaskCase]) -> Result<i64, Fault> {
let Some(value) = values.first() else {
return Ok(0);
};
value
.generated
.run(async |scope| { GENERATED_SYNC(&value.values, scope).await })
.map_err(task_fault)?
.map_err(task_fault)
}
fn reference_sync(values: &[TaskCase]) -> Result<i64, Fault> {
values
.first()
.map_or(Ok(0), |value| value.native.pair(&value.values, false))
}
fn generated_async(values: &[TaskCase]) -> Result<i64, Fault> {
let Some(value) = values.first() else {
return Ok(0);
};
value
.generated
.run(async |scope| { GENERATED_ASYNC(&value.values, scope).await })
.map_err(task_fault)?
.map_err(task_fault)
}
fn reference_async(values: &[TaskCase]) -> Result<i64, Fault> {
values
.first()
.map_or(Ok(0), |value| value.native.pair(&value.values, true))
}
fn generated_parallel(values: &[TaskCase]) -> Result<i64, Fault> {
let Some(value) = values.first() else {
return Ok(0);
};
value
.generated
.run(async |scope| { GENERATED_PARALLEL(&value.values, scope).await })
.map_err(task_fault)?
.map_err(task_fault)
}
fn reference_parallel(values: &[TaskCase]) -> Result<i64, Fault> {
values
.first()
.map_or(Ok(0), |value| value.native.blocking(&value.values, false))
}
fn generated_blocking(values: &[TaskCase]) -> Result<i64, Fault> {
let Some(value) = values.first() else {
return Ok(0);
};
value
.generated
.run(async |scope| { GENERATED_BLOCKING(&value.values, scope).await })
.map_err(task_fault)?
.map_err(task_fault)
}
fn reference_blocking(values: &[TaskCase]) -> Result<i64, Fault> {
values
.first()
.map_or(Ok(0), |value| value.native.blocking(&value.values, true))
}
fn generated_cancel(values: &[TaskCase]) -> Result<i64, Fault> {
let Some(value) = values.first() else {
return Ok(0);
};
value
.generated
.run(async |scope| { GENERATED_CANCEL(scope).await })
.map_err(task_fault)?
.map_err(task_fault)
}
fn reference_cancel(values: &[TaskCase]) -> Result<i64, Fault> {
values.first().map_or(Ok(0), |value| value.native.cancel())
}
fn generated_timer(values: &[TaskCase]) -> Result<i64, Fault> {
let Some(value) = values.first() else {
return Ok(0);
};
value
.generated
.run_leaf(GENERATED_TIMER())
.map_err(task_fault)?
.map_err(task_fault)
}
fn reference_timer(values: &[TaskCase]) -> Result<i64, Fault> {
values.first().map_or(Ok(0), |value| value.native.timer())
}
fn generated_fault(values: &[TaskCase]) -> Result<bool, Fault> {
Ok(generated_sync(values).is_err())
}
fn reference_fault(values: &[TaskCase]) -> Result<bool, Fault> {
Ok(reference_sync(values).is_err())
}
fn main() {
if std::env::args().any(|argument| argument == "--check-cancel-cleanup") {
check_cancel_cleanup();
return;
}
if std::env::args().any(|argument| argument == "--check-worker-cleanup") {
check_worker_cleanup();
return;
}
let cases = [TaskCase {
generated: new_runtime(),
native: NativeTasks::new(),
values: (0..128).collect(),
}];
let expected = native_total(&cases[0].values).unwrap();
assert_eq!(generated_sync(&cases).unwrap(), expected * 2);
assert_eq!(generated_async(&cases).unwrap(), expected * 2);
assert_eq!(generated_parallel(&cases).unwrap(), expected);
assert_eq!(generated_blocking(&cases).unwrap(), expected);
assert_eq!(generated_cancel(&cases).unwrap(), 1);
println!("case,sample,implementation,elapsed_ns,checksum");
compare(
"task_sync_pair",
&cases,
500,
generated_sync,
reference_sync,
|value| *value as u64,
);
compare(
"task_async_pair",
&cases,
1000,
generated_async,
reference_async,
|value| *value as u64,
);
compare(
"task_parallel",
&cases,
500,
generated_parallel,
reference_parallel,
|value| *value as u64,
);
compare(
"task_blocking",
&cases,
500,
generated_blocking,
reference_blocking,
|value| *value as u64,
);
compare(
"task_cancel",
&cases,
1000,
generated_cancel,
reference_cancel,
|value| *value as u64,
);
compare(
"task_timer_zero",
&cases,
10,
generated_timer,
reference_timer,
|value| *value as u64,
);
let failures = [TaskCase {
generated: new_runtime(),
native: NativeTasks::new(),
values: vec![i64::MAX, 1],
}];
assert!(generated_fault(&failures).unwrap());
assert!(generated_async(&failures).is_err());
assert!(reference_async(&failures).is_err());
assert!(shared_async(&failures).is_err());
assert!(shared_worker::<false>(&failures).is_err());
assert!(shared_worker::<true>(&failures).is_err());
assert!(generated_nested(&failures).is_err());
assert!(reference_nested(&failures).is_err());
compare(
"task_sync_fault",
&failures,
500,
generated_fault,
reference_fault,
|value| u64::from(*value),
);
assert!(generated_async_steady(&failures).is_err());
assert!(reference_async_steady(&failures).is_err());
assert!(reference_async_tracked(&failures).is_err());
assert!(reference_async_typed(&failures).is_err());
drop(failures);
lifecycle(&cases);
shared_runtime(&cases);
worker_steady(&cases);
worker_scoped(&cases);
cancel_scoped(&cases);
}