268 lines
8.2 KiB
Rust
268 lines
8.2 KiB
Rust
// 入队计时含具体编码和外层提交;执行计时含真实生成分派、任务作用域、解码、业务写入和确认。
|
|
// 单阶段对照把 claim 放在计时外;完整循环另计入入队、claim、执行和确认。
|
|
struct JobInput {
|
|
name: String,
|
|
amount: i64,
|
|
key: String,
|
|
}
|
|
|
|
fn inputs(count: usize) -> Vec<JobInput> {
|
|
(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<Registry>,
|
|
) -> 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<Claim>,
|
|
scope: &Scope<'_>,
|
|
registry: &Arc<Registry>,
|
|
) -> 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<Registry>, count: usize) -> Vec<Arc<Claim>> {
|
|
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<Registry>,
|
|
generated: bool,
|
|
handler: bool,
|
|
inputs: Vec<JobInput>,
|
|
) -> (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<Registry>,
|
|
generated: bool,
|
|
inputs: Vec<JobInput>,
|
|
) -> (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<Registry>,
|
|
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()
|
|
}
|