// 入队计时含具体编码和外层提交;执行计时含真实生成分派、任务作用域、解码、业务写入和确认。 // 单阶段对照把 claim 放在计时外;完整循环另计入入队、claim、执行和确认。 struct JobInput { name: String, amount: i64, key: String, } fn inputs(count: usize) -> Vec { (0..count) .map(|index| JobInput { name: format!("job-{index:04} 中文\""), amount: index as i64 % 997, key: format!("key-{index:04}"), }) .collect() } async fn submit( generated: bool, input: &JobInput, scope: &Scope<'_>, registry: &Arc, ) -> String { let mut database = DbContext::new(registry.clone()); let owner = database.enter(); let execution = Execution::System { tenant: None }; let id = if generated { GENERATED_SUBMIT( &input.name, input.amount, &input.key, scope, &mut database, &execution, ) .await .unwrap() } else { rust_submit( &input.name, input.amount, &input.key, scope, &mut database, &execution, ) .await .unwrap() }; database.finish(scope, owner, true).await.unwrap(); id.into_text() } async fn execute( generated: bool, claim: Arc, scope: &Scope<'_>, registry: &Arc, ) -> Result<(), JobFailure> { let registry = registry.clone(); let timeout = claim.policy.timeout_ms; let outcome = if generated { scope .spawn(move |child| job_execute(JOB_BINDING, None, claim, child, registry)) .unwrap() .timeout(timeout) .await .unwrap() } else { scope .spawn(move |child| rust_execute(JOB_BINDING, claim, child, registry)) .unwrap() .timeout(timeout) .await .unwrap() }; match outcome { dever_runtime::task::Timed::Ready(value) => value, _ => panic!("benchmark handler timed out"), } } async fn claims(scope: &Scope<'_>, registry: &Arc, count: usize) -> Vec> { let mut database = DbContext::new(registry.clone()); let executor = database.on(JOB_BINDING, scope).await.unwrap(); let mut claims = Vec::with_capacity(count); for _ in 0..count { let claim = job::claim( executor, scope, dever_runtime::database::now().unwrap(), 60000, ) .await .unwrap() .unwrap(); assert_eq!(claim.schema, SCHEMA); assert_eq!(claim.target, TARGET); assert_eq!(claim.attempt, 1); claims.push(Arc::new(claim)); } assert!( job::claim( executor, scope, dever_runtime::database::now().unwrap(), 60000 ) .await .unwrap() .is_none() ); claims } fn measure_jobs( runtime: &Runtime, registry: &Arc, generated: bool, handler: bool, inputs: Vec, ) -> (u128, u64) { runtime .run(async |scope| { clear(scope, registry).await; let claims = if handler { for input in &inputs { black_box(submit(false, input, scope, registry).await); } claims(scope, registry, inputs.len()).await } else { Vec::new() }; let mut checksum = 0u64; let start = Instant::now(); if handler { for claim in claims { execute(generated, black_box(claim), scope, registry) .await .unwrap(); checksum += black_box(1); } } else { for input in &inputs { let id = black_box(submit(generated, black_box(input), scope, registry).await); checksum += id.len() as u64 + input.name.len() as u64 + input.amount as u64; } } let elapsed = start.elapsed().as_nanos(); check_rows(scope, registry, &inputs, handler).await; (elapsed, checksum) }) .unwrap() } fn main() { let (directory, path) = directory("jobs", r#""runtime":{"mode":"worker"}"#); let runtime = runtime(); let registry = runtime .run(async |scope| database_registry(&path, scope).await) .unwrap() .unwrap(); check_jobs(&runtime, ®istry); header(); for (name, handler) in [("job_enqueue_commit", false), ("job_handler_commit", true)] { samples(name, |generated, count| { measure_jobs(&runtime, ®istry, generated, handler, inputs(count)) }); } samples("job_enqueue_large_payload_commit", |generated, count| { let mut inputs = inputs(count.div_ceil(64)); for input in &mut inputs { input.name.push_str(&"a".repeat(64 * 1024)); } measure_jobs(&runtime, ®istry, generated, false, inputs) }); samples("job_submit_claim_complete", |generated, count| { // 完整循环的每个样本包含 250 项实际任务;初始化及独立 SQL 核验不计时。 measure_cycle(&runtime, ®istry, generated, count.div_ceil(8), false) }); samples("job_backlog_claim_complete", |generated, count| { measure_cycle(&runtime, ®istry, generated, count.div_ceil(8), true) }); samples("job_enqueue_duplicate_commit", |generated, count| { measure_duplicate(&runtime, ®istry, generated, inputs(count)) }); drop(registry); drop(runtime); drop(directory); } fn measure_duplicate( runtime: &Runtime, registry: &Arc, generated: bool, inputs: Vec, ) -> (u128, u64) { runtime .run(async |scope| { clear(scope, registry).await; let mut expected = Vec::with_capacity(inputs.len()); for input in &inputs { expected.push(submit(false, input, scope, registry).await); } let mut actual = Vec::with_capacity(inputs.len()); let mut checksum = 0u64; let start = Instant::now(); for input in &inputs { let id = submit(generated, black_box(input), scope, registry).await; checksum += black_box(id.len() as u64); actual.push(id); } let elapsed = start.elapsed().as_nanos(); assert_eq!(actual, expected); check_rows(scope, registry, &inputs, false).await; (elapsed, checksum) }) .unwrap() } fn measure_cycle( runtime: &Runtime, registry: &Arc, generated: bool, count: usize, backlog: bool, ) -> (u128, u64) { let inputs = inputs(count); runtime .run(async |scope| { clear(scope, registry).await; if backlog { for input in &inputs { submit(generated, input, scope, registry).await; } } let start = Instant::now(); let mut checksum = 0u64; for input in &inputs { if !backlog { submit(generated, black_box(input), scope, registry).await; } let claim = { let mut database = DbContext::new(registry.clone()); let executor = database.on(JOB_BINDING, scope).await.unwrap(); job::claim( executor, scope, dever_runtime::database::now().unwrap(), 60000, ) .await .unwrap() .unwrap() }; execute(generated, Arc::new(claim), scope, registry) .await .unwrap(); checksum += black_box(1); } let elapsed = start.elapsed().as_nanos(); check_rows(scope, registry, &inputs, true).await; (elapsed, checksum) }) .unwrap() }