From 220d7c446e58b597f4afd0b6614a7df18dce88ba Mon Sep 17 00:00:00 2001 From: James Ross Date: Sun, 29 Mar 2026 14:24:07 -0700 Subject: [PATCH 01/13] feat(parallel): add adaptive shard routing selector --- crates/warp-benches/benches/README.md | 3 +- .../warp-benches/benches/parallel_baseline.rs | 119 ++-- crates/warp-core/src/lib.rs | 7 +- crates/warp-core/src/parallel/exec.rs | 328 +++++++++- crates/warp-core/src/parallel/mod.rs | 8 +- docs/benchmarks/PARALLEL_POLICY_MATRIX.md | 3 +- docs/benchmarks/index.html | 28 +- docs/benchmarks/parallel-policy-matrix.json | 410 ++++++++----- docs/benchmarks/report-inline.html | 563 ++++++++++-------- 9 files changed, 992 insertions(+), 477 deletions(-) diff --git a/crates/warp-benches/benches/README.md b/crates/warp-benches/benches/README.md index fb073a81..8655bdfc 100644 --- a/crates/warp-benches/benches/README.md +++ b/crates/warp-benches/benches/README.md @@ -33,10 +33,11 @@ results. This README summarizes how to run them and read the output. - static round-robin shard assignment + per-worker deltas - static round-robin shard assignment + per-shard deltas - dedicated one-worker-per-shard + one-delta-per-shard + - adaptive shard routing, which selects a fixed policy from workload shape - Each case includes canonical delta merge after parallel execution, so the study reflects full policy cost for the synthetic independent workload. - The policy matrix runs across loads `100`, `1000`, and `10000`, with worker - counts `1`, `4`, and `8` where the policy uses a worker pool. + hints `1`, `4`, and `8` where the policy uses a worker pool. - Throughput “elements” = executed items in the synthetic independent workload. ## Run diff --git a/crates/warp-benches/benches/parallel_baseline.rs b/crates/warp-benches/benches/parallel_baseline.rs index 426f18f1..dc7b5de2 100644 --- a/crates/warp-benches/benches/parallel_baseline.rs +++ b/crates/warp-benches/benches/parallel_baseline.rs @@ -27,9 +27,10 @@ use std::num::NonZeroUsize; use std::time::Duration; use warp_core::parallel::{build_work_units, execute_work_queue, WorkerResult}; use warp_core::{ - execute_parallel, execute_parallel_with_policy, execute_serial, make_node_id, make_type_id, - make_warp_id, AtomPayload, AttachmentKey, AttachmentValue, ExecItem, GraphStore, GraphView, - NodeId, NodeKey, NodeRecord, OpOrigin, ParallelExecutionPolicy, TickDelta, WarpId, WarpOp, + execute_parallel, execute_parallel_with_policy, execute_parallel_with_selector, execute_serial, + make_node_id, make_type_id, make_warp_id, AdaptiveShardRoutingSelector, AtomPayload, + AttachmentKey, AttachmentValue, ExecItem, GraphStore, GraphView, NodeId, NodeKey, NodeRecord, + OpOrigin, ParallelExecutionPolicy, TickDelta, WarpId, WarpOp, }; /// Simple executor that sets an attachment on the scope node. @@ -317,14 +318,27 @@ fn bench_worker_scaling(c: &mut Criterion) { // Policy matrix comparison // ============================================================================= -fn policy_label(policy: ParallelExecutionPolicy) -> &'static str { - match policy { - ParallelExecutionPolicy::DYNAMIC_PER_WORKER => "dynamic_per_worker", - ParallelExecutionPolicy::DYNAMIC_PER_SHARD => "dynamic_per_shard", - ParallelExecutionPolicy::STATIC_PER_WORKER => "static_per_worker", - ParallelExecutionPolicy::STATIC_PER_SHARD => "static_per_shard", - ParallelExecutionPolicy::DEDICATED_PER_SHARD => "dedicated_per_shard", - _ => panic!("unmapped ParallelExecutionPolicy in parallel_policy_matrix"), +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum PolicyMatrixCase { + Fixed(ParallelExecutionPolicy), + Adaptive, +} + +fn policy_case_label(case: PolicyMatrixCase) -> &'static str { + match case { + PolicyMatrixCase::Fixed(ParallelExecutionPolicy::DYNAMIC_PER_WORKER) => { + "dynamic_per_worker" + } + PolicyMatrixCase::Fixed(ParallelExecutionPolicy::DYNAMIC_PER_SHARD) => "dynamic_per_shard", + PolicyMatrixCase::Fixed(ParallelExecutionPolicy::STATIC_PER_WORKER) => "static_per_worker", + PolicyMatrixCase::Fixed(ParallelExecutionPolicy::STATIC_PER_SHARD) => "static_per_shard", + PolicyMatrixCase::Fixed(ParallelExecutionPolicy::DEDICATED_PER_SHARD) => { + "dedicated_per_shard" + } + PolicyMatrixCase::Fixed(_) => { + panic!("unmapped ParallelExecutionPolicy in parallel_policy_matrix") + } + PolicyMatrixCase::Adaptive => "adaptive_shard_routing", } } @@ -344,41 +358,21 @@ fn bench_policy_matrix(c: &mut Criterion) { .measurement_time(Duration::from_secs(5)) .sample_size(40); - let policies = [ - ParallelExecutionPolicy::DYNAMIC_PER_WORKER, - ParallelExecutionPolicy::DYNAMIC_PER_SHARD, - ParallelExecutionPolicy::STATIC_PER_WORKER, - ParallelExecutionPolicy::STATIC_PER_SHARD, - ParallelExecutionPolicy::DEDICATED_PER_SHARD, + let cases = [ + PolicyMatrixCase::Fixed(ParallelExecutionPolicy::DYNAMIC_PER_WORKER), + PolicyMatrixCase::Fixed(ParallelExecutionPolicy::DYNAMIC_PER_SHARD), + PolicyMatrixCase::Fixed(ParallelExecutionPolicy::STATIC_PER_WORKER), + PolicyMatrixCase::Fixed(ParallelExecutionPolicy::STATIC_PER_SHARD), + PolicyMatrixCase::Fixed(ParallelExecutionPolicy::DEDICATED_PER_SHARD), + PolicyMatrixCase::Adaptive, ]; for &n in &[100usize, 1_000, 10_000] { group.throughput(Throughput::Elements(n as u64)); - for policy in policies { - if policy == ParallelExecutionPolicy::DEDICATED_PER_SHARD { - group.bench_with_input(BenchmarkId::new(policy_label(policy), n), &n, |b, &n| { - b.iter_batched( - || { - let (store, nodes) = make_test_store(n); - let items = make_exec_items(&nodes); - (store, items) - }, - |(store, items)| { - let view = GraphView::new(&store); - let deltas = - execute_parallel_with_policy(view, &items, worker_hint(1), policy); - let merged = merge_for_commit_path(deltas); - criterion::black_box(merged) - }, - BatchSize::SmallInput, - ); - }); - continue; - } - - for &workers in &[1usize, 4, 8] { + for case in cases { + if case == PolicyMatrixCase::Fixed(ParallelExecutionPolicy::DEDICATED_PER_SHARD) { group.bench_with_input( - BenchmarkId::new(format!("{}/{}w", policy_label(policy), workers), n), + BenchmarkId::new(policy_case_label(case), n), &n, |b, &n| { b.iter_batched( @@ -392,8 +386,8 @@ fn bench_policy_matrix(c: &mut Criterion) { let deltas = execute_parallel_with_policy( view, &items, - worker_hint(workers), - policy, + worker_hint(1), + ParallelExecutionPolicy::DEDICATED_PER_SHARD, ); let merged = merge_for_commit_path(deltas); criterion::black_box(merged) @@ -402,6 +396,45 @@ fn bench_policy_matrix(c: &mut Criterion) { ); }, ); + continue; + } + + for &workers in &[1usize, 4, 8] { + group.bench_with_input( + BenchmarkId::new(format!("{}/{}w", policy_case_label(case), workers), n), + &n, + |b, &n| { + b.iter_batched( + || { + let (store, nodes) = make_test_store(n); + let items = make_exec_items(&nodes); + (store, items) + }, + |(store, items)| { + let view = GraphView::new(&store); + let deltas = match case { + PolicyMatrixCase::Fixed(policy) => { + execute_parallel_with_policy( + view, + &items, + worker_hint(workers), + policy, + ) + } + PolicyMatrixCase::Adaptive => execute_parallel_with_selector( + view, + &items, + worker_hint(workers), + AdaptiveShardRoutingSelector, + ), + }; + let merged = merge_for_commit_path(deltas); + criterion::black_box(merged) + }, + BatchSize::SmallInput, + ); + }, + ); } } } diff --git a/crates/warp-core/src/lib.rs b/crates/warp-core/src/lib.rs index 595808c2..b52f0676 100644 --- a/crates/warp-core/src/lib.rs +++ b/crates/warp-core/src/lib.rs @@ -168,8 +168,11 @@ pub use ident::{ }; pub use parallel::{ execute_parallel, execute_parallel_sharded, execute_parallel_sharded_with_policy, - execute_parallel_with_policy, execute_serial, shard_of, DeltaAccumulationPolicy, ExecItem, - MergeConflict, ParallelExecutionPolicy, PoisonedDelta, ShardAssignmentPolicy, NUM_SHARDS, + execute_parallel_sharded_with_selector, execute_parallel_with_policy, + execute_parallel_with_selector, execute_serial, shard_of, AdaptiveShardRoutingSelector, + DeltaAccumulationPolicy, ExecItem, MergeConflict, ParallelExecutionPlan, + ParallelExecutionPlanSelector, ParallelExecutionPolicy, ParallelExecutionWorkloadProfile, + PoisonedDelta, ShardAssignmentPolicy, NUM_SHARDS, }; /// Delta merging functions, only available with `delta_validate` feature. /// diff --git a/crates/warp-core/src/parallel/exec.rs b/crates/warp-core/src/parallel/exec.rs index bbb81b84..166f5f59 100644 --- a/crates/warp-core/src/parallel/exec.rs +++ b/crates/warp-core/src/parallel/exec.rs @@ -109,6 +109,157 @@ impl ParallelExecutionPolicy { } } +/// Lightweight shape summary of a shard-partitioned parallel workload. +/// +/// This profile is deterministic and cheap to derive once `partition_into_shards()` +/// has already grouped items by shard. Selectors can use it to choose a stable +/// execution plan without inspecting machine-local runtime state. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct ParallelExecutionWorkloadProfile { + total_items: usize, + non_empty_shards: usize, + max_shard_len: usize, +} + +impl ParallelExecutionWorkloadProfile { + /// Creates a workload profile from aggregate counts. + #[must_use] + pub const fn new(total_items: usize, non_empty_shards: usize, max_shard_len: usize) -> Self { + Self { + total_items, + non_empty_shards, + max_shard_len, + } + } + + /// Returns the total number of items in the workload. + #[must_use] + pub const fn total_items(self) -> usize { + self.total_items + } + + /// Returns the number of non-empty virtual shards in the workload. + #[must_use] + pub const fn non_empty_shards(self) -> usize { + self.non_empty_shards + } + + /// Returns the size of the largest non-empty virtual shard. + #[must_use] + pub const fn max_shard_len(self) -> usize { + self.max_shard_len + } + + fn from_shards(shards: &[super::shard::VirtualShard]) -> Self { + let mut total_items = 0; + let mut non_empty_shards = 0; + let mut max_shard_len = 0; + + for shard in shards { + let shard_len = shard.items.len(); + total_items += shard_len; + if shard_len > 0 { + non_empty_shards += 1; + max_shard_len = max_shard_len.max(shard_len); + } + } + + Self::new(total_items, non_empty_shards, max_shard_len) + } +} + +/// Resolved plan for one parallel execution attempt. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct ParallelExecutionPlan { + workers: NonZeroUsize, + policy: ParallelExecutionPolicy, +} + +impl ParallelExecutionPlan { + /// Creates a new plan from a worker count and fixed execution policy. + #[must_use] + pub const fn new(workers: NonZeroUsize, policy: ParallelExecutionPolicy) -> Self { + Self { workers, policy } + } + + /// Returns the worker count selected for this execution. + #[must_use] + pub const fn workers(self) -> NonZeroUsize { + self.workers + } + + /// Returns the fixed execution policy selected for this execution. + #[must_use] + pub const fn policy(self) -> ParallelExecutionPolicy { + self.policy + } +} + +/// Selects a deterministic parallel execution plan from a worker hint and workload profile. +pub trait ParallelExecutionPlanSelector { + /// Chooses the fixed execution plan to use for this workload. + fn select_plan( + &self, + worker_hint: NonZeroUsize, + workload: ParallelExecutionWorkloadProfile, + ) -> ParallelExecutionPlan; +} + +/// Workload-aware selector for shard-routing policy experiments. +/// +/// The heuristic is intentionally conservative: +/// - very small or effectively serial workloads collapse to `STATIC_PER_WORKER` on `1w` +/// - medium workloads use `DYNAMIC_PER_WORKER` on `1w` +/// - large, well-distributed workloads switch to `DYNAMIC_PER_SHARD` with up to `4w` +/// +/// This selector is meant for benchmarking and tuning. It does not observe +/// ambient machine state and remains a pure function of workload shape. +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct AdaptiveShardRoutingSelector; + +const ADAPTIVE_SMALL_WORKLOAD_ITEMS: usize = 256; +const ADAPTIVE_LARGE_WORKLOAD_ITEMS: usize = 4_096; +const ADAPTIVE_MIN_PARALLEL_SHARDS: usize = 4; +const ADAPTIVE_DYNAMIC_PER_SHARD_WORKERS: usize = 4; + +impl ParallelExecutionPlanSelector for AdaptiveShardRoutingSelector { + fn select_plan( + &self, + worker_hint: NonZeroUsize, + workload: ParallelExecutionWorkloadProfile, + ) -> ParallelExecutionPlan { + let effective_shard_parallelism = workload.non_empty_shards().min(worker_hint.get()).max(1); + + if workload.total_items() <= ADAPTIVE_SMALL_WORKLOAD_ITEMS + || effective_shard_parallelism <= 1 + { + return ParallelExecutionPlan::new( + NonZeroUsize::MIN, + ParallelExecutionPolicy::STATIC_PER_WORKER, + ); + } + + if workload.total_items() >= ADAPTIVE_LARGE_WORKLOAD_ITEMS + && effective_shard_parallelism >= ADAPTIVE_MIN_PARALLEL_SHARDS + && workload.max_shard_len().saturating_mul(2) <= workload.total_items() + { + let workers = non_zero( + worker_hint + .get() + .min(ADAPTIVE_DYNAMIC_PER_SHARD_WORKERS) + .min(workload.non_empty_shards()) + .max(1), + ); + return ParallelExecutionPlan::new(workers, ParallelExecutionPolicy::DYNAMIC_PER_SHARD); + } + + ParallelExecutionPlan::new( + NonZeroUsize::MIN, + ParallelExecutionPolicy::DYNAMIC_PER_WORKER, + ) + } +} + impl Default for ParallelExecutionPolicy { fn default() -> Self { Self::DEFAULT @@ -264,8 +415,7 @@ pub fn execute_parallel(view: GraphView<'_>, items: &[ExecItem], workers: usize) assert!(workers >= 1, "need at least one worker"); // Cap workers at NUM_SHARDS - no point spawning 512 threads for 256 shards - let capped_workers = - NonZeroUsize::new(workers.min(NUM_SHARDS)).map_or(NonZeroUsize::MIN, |w| w); + let capped_workers = capped_workers(non_zero(workers)); execute_parallel_sharded_with_policy( view, @@ -301,7 +451,7 @@ pub fn execute_parallel_sharded( workers: usize, ) -> Vec { assert!(workers >= 1, "need at least one worker"); - let workers = NonZeroUsize::new(workers).map_or(NonZeroUsize::MIN, |w| w); + let workers = non_zero(workers); execute_parallel_sharded_with_policy(view, items, workers, ParallelExecutionPolicy::DEFAULT) } @@ -321,43 +471,67 @@ pub fn execute_parallel_sharded_with_policy( workers: NonZeroUsize, policy: ParallelExecutionPolicy, ) -> Vec { - let workers = workers.get(); - - if items.is_empty() { - return match policy.assignment { - ShardAssignmentPolicy::DedicatedPerShard => Vec::new(), - _ => { - // Can't use vec![TickDelta::new(); workers] because TickDelta doesn't impl Clone - (0..workers).map(|_| TickDelta::new()).collect() - } + let workers = capped_workers(workers); + let shards = partition_into_shards(items); + execute_partitioned_shards(view, &shards, ParallelExecutionPlan::new(workers, policy)) +} + +/// Parallel execution with a selector that can adapt the plan to workload shape. +pub fn execute_parallel_sharded_with_selector( + view: GraphView<'_>, + items: &[ExecItem], + workers: NonZeroUsize, + selector: S, +) -> Vec +where + S: ParallelExecutionPlanSelector, +{ + let workers = capped_workers(workers); + let shards = partition_into_shards(items); + let workload = ParallelExecutionWorkloadProfile::from_shards(&shards); + let plan = selector.select_plan(workers, workload); + execute_partitioned_shards(view, &shards, plan) +} + +fn execute_partitioned_shards( + view: GraphView<'_>, + shards: &[super::shard::VirtualShard], + plan: ParallelExecutionPlan, +) -> Vec { + let workload = ParallelExecutionWorkloadProfile::from_shards(shards); + if workload.total_items() == 0 { + return if plan.policy().assignment == ShardAssignmentPolicy::DedicatedPerShard { + Vec::new() + } else { + let workers = capped_workers(plan.workers()).get(); + (0..workers).map(|_| TickDelta::new()).collect() }; } - // Partition into virtual shards by scope - let shards = partition_into_shards(items); - match (policy.assignment, policy.accumulation) { + let workers = capped_workers(plan.workers()).get(); + match (plan.policy().assignment(), plan.policy().accumulation()) { (ShardAssignmentPolicy::DynamicSteal, DeltaAccumulationPolicy::PerWorker) => { - execute_dynamic_per_worker(view, &shards, workers) + execute_dynamic_per_worker(view, shards, workers) } (ShardAssignmentPolicy::DynamicSteal, DeltaAccumulationPolicy::PerShard) => { - execute_dynamic_per_shard(view, &shards, workers) + execute_dynamic_per_shard(view, shards, workers) } (ShardAssignmentPolicy::StaticRoundRobin, DeltaAccumulationPolicy::PerWorker) => { - execute_static_per_worker(view, &shards, workers) + execute_static_per_worker(view, shards, workers) } (ShardAssignmentPolicy::StaticRoundRobin, DeltaAccumulationPolicy::PerShard) => { - execute_static_per_shard(view, &shards, workers) + execute_static_per_shard(view, shards, workers) } ( ShardAssignmentPolicy::DedicatedPerShard, DeltaAccumulationPolicy::PerWorker | DeltaAccumulationPolicy::PerShard, ) => { debug_assert_eq!( - policy.accumulation, + plan.policy().accumulation(), DeltaAccumulationPolicy::PerShard, "DedicatedPerShard is only exposed with PerShard accumulation" ); - execute_dedicated_per_shard(view, &shards) + execute_dedicated_per_shard(view, shards) } } } @@ -372,9 +546,35 @@ pub fn execute_parallel_with_policy( workers: NonZeroUsize, policy: ParallelExecutionPolicy, ) -> Vec { - let capped_workers = - NonZeroUsize::new(workers.get().min(NUM_SHARDS)).map_or(NonZeroUsize::MIN, |w| w); - execute_parallel_sharded_with_policy(view, items, capped_workers, policy) + execute_parallel_sharded_with_policy(view, items, capped_workers(workers), policy) +} + +/// Parallel execution entry point with a selector that may adapt policy and worker count. +pub fn execute_parallel_with_selector( + view: GraphView<'_>, + items: &[ExecItem], + workers: NonZeroUsize, + selector: S, +) -> Vec +where + S: ParallelExecutionPlanSelector, +{ + execute_parallel_sharded_with_selector(view, items, capped_workers(workers), selector) +} + +const fn non_zero(value: usize) -> NonZeroUsize { + match NonZeroUsize::new(value) { + Some(value) => value, + None => NonZeroUsize::MIN, + } +} + +const fn capped_workers(workers: NonZeroUsize) -> NonZeroUsize { + non_zero(if workers.get() < NUM_SHARDS { + workers.get() + } else { + NUM_SHARDS + }) } fn execute_shard_into_delta(view: GraphView<'_>, items: &[ExecItem], delta: &mut TickDelta) { @@ -853,7 +1053,11 @@ fn execute_item_enforced( #[cfg(test)] mod tests { - use super::{execute_parallel_with_policy, ExecItem, ParallelExecutionPolicy}; + use super::{ + execute_parallel_with_policy, execute_parallel_with_selector, AdaptiveShardRoutingSelector, + ExecItem, ParallelExecutionPlan, ParallelExecutionPlanSelector, ParallelExecutionPolicy, + ParallelExecutionWorkloadProfile, + }; use crate::{ execute_serial, make_type_id, merge_deltas_ok, AtomPayload, AttachmentKey, AttachmentValue, GraphStore, GraphView, NodeId, NodeKey, NodeRecord, OpOrigin, TickDelta, WarpOp, @@ -906,6 +1110,48 @@ mod tests { NonZeroUsize::new(workers.max(1)).map_or(NonZeroUsize::MIN, |w| w) } + #[test] + fn adaptive_selector_prefers_static_per_worker_for_small_workloads() { + let selector = AdaptiveShardRoutingSelector; + let plan = selector.select_plan( + worker_hint(8), + ParallelExecutionWorkloadProfile::new(100, 100, 1), + ); + + assert_eq!( + plan, + ParallelExecutionPlan::new(worker_hint(1), ParallelExecutionPolicy::STATIC_PER_WORKER) + ); + } + + #[test] + fn adaptive_selector_prefers_dynamic_per_worker_for_medium_workloads() { + let selector = AdaptiveShardRoutingSelector; + let plan = selector.select_plan( + worker_hint(8), + ParallelExecutionWorkloadProfile::new(1_000, 32, 48), + ); + + assert_eq!( + plan, + ParallelExecutionPlan::new(worker_hint(1), ParallelExecutionPolicy::DYNAMIC_PER_WORKER) + ); + } + + #[test] + fn adaptive_selector_prefers_dynamic_per_shard_for_large_wide_workloads() { + let selector = AdaptiveShardRoutingSelector; + let plan = selector.select_plan( + worker_hint(8), + ParallelExecutionWorkloadProfile::new(10_000, 64, 120), + ); + + assert_eq!( + plan, + ParallelExecutionPlan::new(worker_hint(4), ParallelExecutionPolicy::DYNAMIC_PER_SHARD) + ); + } + #[test] fn all_parallel_policies_match_serial_oracle() { let policies = [ @@ -1081,4 +1327,36 @@ mod tests { "empty workload should produce no deltas for dedicated-per-shard" ); } + + #[test] + fn adaptive_selector_matches_serial_oracle() { + let selector = AdaptiveShardRoutingSelector; + let (store, items) = make_store_and_items(64); + let view = GraphView::new(&store); + let serial_oracle_result = merge_deltas_ok(vec![execute_serial(view, &items)]); + assert!( + serial_oracle_result.is_ok(), + "serial oracle merge failed for adaptive selector: {serial_oracle_result:?}" + ); + let Ok(serial_oracle) = serial_oracle_result else { + unreachable!("assert above guarantees a valid serial oracle"); + }; + + for workers in [1_usize, 4, 8] { + let deltas = + execute_parallel_with_selector(view, &items, worker_hint(workers), selector); + let merged_result = merge_deltas_ok(deltas); + assert!( + merged_result.is_ok(), + "adaptive selector merge failed at {workers}w: {merged_result:?}" + ); + let Ok(merged) = merged_result else { + unreachable!("assert above guarantees a valid adaptive merge"); + }; + assert_eq!( + merged, serial_oracle, + "adaptive selector changed merged ops at {workers}w" + ); + } + } } diff --git a/crates/warp-core/src/parallel/mod.rs b/crates/warp-core/src/parallel/mod.rs index cc7ceaa3..0fcc4156 100644 --- a/crates/warp-core/src/parallel/mod.rs +++ b/crates/warp-core/src/parallel/mod.rs @@ -13,9 +13,11 @@ pub mod shard; pub(crate) use exec::ExecItemKind; pub use exec::{ build_work_units, execute_parallel, execute_parallel_sharded, - execute_parallel_sharded_with_policy, execute_parallel_with_policy, execute_serial, - execute_work_queue, DeltaAccumulationPolicy, ExecItem, ParallelExecutionPolicy, PoisonedDelta, - ShardAssignmentPolicy, WorkUnit, WorkerResult, + execute_parallel_sharded_with_policy, execute_parallel_sharded_with_selector, + execute_parallel_with_policy, execute_parallel_with_selector, execute_serial, + execute_work_queue, AdaptiveShardRoutingSelector, DeltaAccumulationPolicy, ExecItem, + ParallelExecutionPlan, ParallelExecutionPlanSelector, ParallelExecutionPolicy, + ParallelExecutionWorkloadProfile, PoisonedDelta, ShardAssignmentPolicy, WorkUnit, WorkerResult, }; #[cfg(not(any(test, feature = "delta_validate")))] pub(crate) use merge::check_write_to_new_warp; diff --git a/docs/benchmarks/PARALLEL_POLICY_MATRIX.md b/docs/benchmarks/PARALLEL_POLICY_MATRIX.md index facc897c..941a9292 100644 --- a/docs/benchmarks/PARALLEL_POLICY_MATRIX.md +++ b/docs/benchmarks/PARALLEL_POLICY_MATRIX.md @@ -13,6 +13,7 @@ count: - static round-robin shard assignment + one delta per worker - static round-robin shard assignment + one delta per shard - dedicated one-worker-per-shard + one delta per shard +- adaptive shard routing, which selects one of the pooled-worker policies from workload shape The point is to answer a narrower question than "is parallel good?": @@ -32,7 +33,7 @@ The benchmark currently runs at: - `1000` - `10000` -For pooled-worker policies, it also varies worker counts: +For pooled-worker policies, it also varies worker hints: - `1` - `4` diff --git a/docs/benchmarks/index.html b/docs/benchmarks/index.html index 747bca71..98370be2 100644 --- a/docs/benchmarks/index.html +++ b/docs/benchmarks/index.html @@ -849,6 +849,7 @@

Raw policy table

static_per_worker: "#fbbf24", static_per_shard: "#fb7185", dedicated_per_shard: "#c084fc", + adaptive_shard_routing: "#f97316", }; const POLICY_LABELS = { dynamic_per_worker: "Dynamic claim / worker delta", @@ -856,6 +857,7 @@

Raw policy table

static_per_worker: "Static round-robin / worker delta", static_per_shard: "Static round-robin / shard delta", dedicated_per_shard: "Dedicated shard / shard delta", + adaptive_shard_routing: "Adaptive shard routing selector", }; const WORKER_DASH = { "1w": null, @@ -1654,8 +1656,17 @@

Raw policy table

const winnerSeq = rankedLoads .map(({ rows }) => rows[0].workers) .join(" → "); - const staticWinsAll = rankedLoads.every( - ({ rows }) => rows[0].policy === "static_per_worker", + const sameWinnerFamily = rankedLoads.every( + ({ rows }) => + rows[0].policy === rankedLoads[0].rows[0].policy, + ); + const adaptiveLeadsAnyLoad = rankedLoads.some( + ({ rows }) => rows[0].policy === "adaptive_shard_routing", + ); + const adaptiveFrontPack = rankedLoads.every(({ rows }) => + rows + .slice(0, 3) + .some((row) => row.policy === "adaptive_shard_routing"), ); const dedicatedAlwaysLast = rankedLoads.every( ({ rows }) => @@ -1670,9 +1681,9 @@

Raw policy table

`The front pair overlap on confidence intervals for ${tiedFrontLoads.join(", ")}, so trust those loads as close races rather than clean one-policy wins.`, ); } - if (staticWinsAll) { + if (sameWinnerFamily) { lines.push( - "Static round-robin with one delta per worker wins every tested load on this machine, so the simpler pooled-worker path is setting the pace in this study.", + `${POLICY_LABELS[rankedLoads[0].rows[0].policy] ?? rankedLoads[0].rows[0].policy} leads every tested load on this machine, so one policy family is clearly setting the pace in this study.`, ); } if (winnerSeq === "1w → 4w → 8w") { @@ -1680,6 +1691,15 @@

Raw policy table

"As load rises, the winning worker pool widens step by step. Small work prefers less coordination; heavier work finally justifies a wider pool.", ); } + if (adaptiveLeadsAnyLoad) { + lines.push( + "The workload-aware selector does win at least one tested load, which means the heuristic is not just a convenience wrapper around the slower half of the field.", + ); + } else if (adaptiveFrontPack) { + lines.push( + "The workload-aware selector stays in the front pack across the sweep, even when a fixed policy edges it out on individual loads.", + ); + } if (dedicatedAlwaysLast) { lines.push( "The dedicated one-thread-per-shard extreme never catches the field. It is useful as a boundary case, not as a promising default.", diff --git a/docs/benchmarks/parallel-policy-matrix.json b/docs/benchmarks/parallel-policy-matrix.json index 1afe5011..5a5d6849 100644 --- a/docs/benchmarks/parallel-policy-matrix.json +++ b/docs/benchmarks/parallel-policy-matrix.json @@ -1,8 +1,8 @@ { "group": "parallel_policy_matrix", - "baked_at": "2026-03-29T19:51:34.009982Z", - "baked_git_sha": "c235096", - "baked_source_digest": "7510f1cdabaeb08c4550190c225794d4871c9fb18a916d639ad4f42eb8367521", + "baked_at": "2026-03-29T21:21:34.054072Z", + "baked_git_sha": "2629822", + "baked_source_digest": "5389879acbd17e7600bbc023534c29128392ea9c2c9c0a84cd66878c238c833c", "template_path": "docs/benchmarks/index.html", "machine": { "os": "macos", @@ -10,396 +10,486 @@ "hostname": null, "label": "macos/aarch64" }, - "criterion_root": "target/criterion/parallel_policy_matrix", + "criterion_root": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix", "results": [ + { + "policy": "adaptive_shard_routing", + "workers": "1w", + "load": 100, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/adaptive_shard_routing_1w/100/new/estimates.json", + "mean_ns": 44358.44937786946, + "lb_ns": 43323.33601944532, + "ub_ns": 45576.88374992756, + "series": "adaptive_shard_routing:1w" + }, + { + "policy": "adaptive_shard_routing", + "workers": "1w", + "load": 1000, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/adaptive_shard_routing_1w/1000/new/estimates.json", + "mean_ns": 287097.46716856764, + "lb_ns": 279982.17584852513, + "ub_ns": 298445.19017925614, + "series": "adaptive_shard_routing:1w" + }, + { + "policy": "adaptive_shard_routing", + "workers": "1w", + "load": 10000, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/adaptive_shard_routing_1w/10000/new/estimates.json", + "mean_ns": 2857013.301690193, + "lb_ns": 2809455.758295108, + "ub_ns": 2909350.275664746, + "series": "adaptive_shard_routing:1w" + }, { "policy": "dynamic_per_shard", "workers": "1w", "load": 100, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_shard_1w/100/new/estimates.json", - "mean_ns": 55464.43408260571, - "lb_ns": 54756.69361375341, - "ub_ns": 56202.66931437411, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_shard_1w/100/new/estimates.json", + "mean_ns": 51782.982030376435, + "lb_ns": 51227.24740338251, + "ub_ns": 52347.3023288871, "series": "dynamic_per_shard:1w" }, { "policy": "dynamic_per_shard", "workers": "1w", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_shard_1w/1000/new/estimates.json", - "mean_ns": 343427.6850951146, - "lb_ns": 319083.4070900986, - "ub_ns": 373475.23771829135, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_shard_1w/1000/new/estimates.json", + "mean_ns": 283681.728942981, + "lb_ns": 282117.3005074449, + "ub_ns": 285312.42791421036, "series": "dynamic_per_shard:1w" }, { "policy": "dynamic_per_shard", "workers": "1w", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_shard_1w/10000/new/estimates.json", - "mean_ns": 4201208.348823542, - "lb_ns": 3875169.7980738874, - "ub_ns": 4567399.876901627, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_shard_1w/10000/new/estimates.json", + "mean_ns": 2760061.691373654, + "lb_ns": 2739153.2713815016, + "ub_ns": 2780761.1589381625, "series": "dynamic_per_shard:1w" }, { "policy": "dynamic_per_worker", "workers": "1w", "load": 100, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_worker_1w/100/new/estimates.json", - "mean_ns": 118001.1679377424, - "lb_ns": 106180.36814934696, - "ub_ns": 135372.81707939805, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_worker_1w/100/new/estimates.json", + "mean_ns": 41494.465293701665, + "lb_ns": 41288.696662957205, + "ub_ns": 41700.594159852575, "series": "dynamic_per_worker:1w" }, { "policy": "dynamic_per_worker", "workers": "1w", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_worker_1w/1000/new/estimates.json", - "mean_ns": 270892.1481032658, - "lb_ns": 267017.7138902802, - "ub_ns": 275278.0843480539, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_worker_1w/1000/new/estimates.json", + "mean_ns": 245355.26027854352, + "lb_ns": 242557.484907688, + "ub_ns": 248624.58833234227, "series": "dynamic_per_worker:1w" }, { "policy": "dynamic_per_worker", "workers": "1w", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_worker_1w/10000/new/estimates.json", - "mean_ns": 2762096.073968301, - "lb_ns": 2691334.9446979314, - "ub_ns": 2853504.588098411, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_worker_1w/10000/new/estimates.json", + "mean_ns": 2694552.797965237, + "lb_ns": 2636740.4622011464, + "ub_ns": 2782135.960233458, "series": "dynamic_per_worker:1w" }, { "policy": "static_per_shard", "workers": "1w", "load": 100, - "path": "target/criterion/parallel_policy_matrix/static_per_shard_1w/100/new/estimates.json", - "mean_ns": 68038.9133507309, - "lb_ns": 60144.881347430055, - "ub_ns": 78999.4423918486, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_shard_1w/100/new/estimates.json", + "mean_ns": 51977.80048241994, + "lb_ns": 51605.88969510445, + "ub_ns": 52403.59267952765, "series": "static_per_shard:1w" }, { "policy": "static_per_shard", "workers": "1w", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/static_per_shard_1w/1000/new/estimates.json", - "mean_ns": 315397.2679475274, - "lb_ns": 298548.79247113975, - "ub_ns": 338033.46786511806, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_shard_1w/1000/new/estimates.json", + "mean_ns": 269597.1454368831, + "lb_ns": 266944.13558178436, + "ub_ns": 272638.0293596035, "series": "static_per_shard:1w" }, { "policy": "static_per_shard", "workers": "1w", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/static_per_shard_1w/10000/new/estimates.json", - "mean_ns": 3253597.341064291, - "lb_ns": 3174288.7754920344, - "ub_ns": 3339159.0839692825, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_shard_1w/10000/new/estimates.json", + "mean_ns": 2923424.8518555355, + "lb_ns": 2914042.5912258644, + "ub_ns": 2932980.6251611565, "series": "static_per_shard:1w" }, { "policy": "static_per_worker", "workers": "1w", "load": 100, - "path": "target/criterion/parallel_policy_matrix/static_per_worker_1w/100/new/estimates.json", - "mean_ns": 51739.36454908365, - "lb_ns": 48378.98747472938, - "ub_ns": 56425.19122588916, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_worker_1w/100/new/estimates.json", + "mean_ns": 43914.67268938888, + "lb_ns": 43339.21209537024, + "ub_ns": 44577.86675452289, "series": "static_per_worker:1w" }, { "policy": "static_per_worker", "workers": "1w", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/static_per_worker_1w/1000/new/estimates.json", - "mean_ns": 305768.3191330779, - "lb_ns": 289677.7784319992, - "ub_ns": 325951.6131473716, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_worker_1w/1000/new/estimates.json", + "mean_ns": 241234.82362317815, + "lb_ns": 240025.06485324135, + "ub_ns": 242484.0202472527, "series": "static_per_worker:1w" }, { "policy": "static_per_worker", "workers": "1w", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/static_per_worker_1w/10000/new/estimates.json", - "mean_ns": 4339330.832882105, - "lb_ns": 3776273.4789978, - "ub_ns": 4967749.246199884, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_worker_1w/10000/new/estimates.json", + "mean_ns": 2870005.5788555704, + "lb_ns": 2740352.8105393457, + "ub_ns": 3010568.646472883, "series": "static_per_worker:1w" }, + { + "policy": "adaptive_shard_routing", + "workers": "4w", + "load": 100, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/adaptive_shard_routing_4w/100/new/estimates.json", + "mean_ns": 54391.53862284124, + "lb_ns": 50036.64670734555, + "ub_ns": 59415.90332238293, + "series": "adaptive_shard_routing:4w" + }, + { + "policy": "adaptive_shard_routing", + "workers": "4w", + "load": 1000, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/adaptive_shard_routing_4w/1000/new/estimates.json", + "mean_ns": 288823.1466228908, + "lb_ns": 279095.95939006266, + "ub_ns": 302067.29946582887, + "series": "adaptive_shard_routing:4w" + }, + { + "policy": "adaptive_shard_routing", + "workers": "4w", + "load": 10000, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/adaptive_shard_routing_4w/10000/new/estimates.json", + "mean_ns": 2149423.2770749717, + "lb_ns": 2134908.374596005, + "ub_ns": 2167505.4383061337, + "series": "adaptive_shard_routing:4w" + }, { "policy": "dynamic_per_shard", "workers": "4w", "load": 100, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_shard_4w/100/new/estimates.json", - "mean_ns": 94623.96109289848, - "lb_ns": 92672.9358013662, - "ub_ns": 96862.53591063726, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_shard_4w/100/new/estimates.json", + "mean_ns": 94078.68169012797, + "lb_ns": 92275.40674576764, + "ub_ns": 95655.80750085563, "series": "dynamic_per_shard:4w" }, { "policy": "dynamic_per_shard", "workers": "4w", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_shard_4w/1000/new/estimates.json", - "mean_ns": 291516.0789781246, - "lb_ns": 285026.3822294185, - "ub_ns": 299125.50646760175, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_shard_4w/1000/new/estimates.json", + "mean_ns": 256253.96598205468, + "lb_ns": 253698.59471801095, + "ub_ns": 258912.63292844972, "series": "dynamic_per_shard:4w" }, { "policy": "dynamic_per_shard", "workers": "4w", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_shard_4w/10000/new/estimates.json", - "mean_ns": 2312237.6050062696, - "lb_ns": 2254378.0920585655, - "ub_ns": 2388842.6003074846, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_shard_4w/10000/new/estimates.json", + "mean_ns": 2072618.4615597, + "lb_ns": 2063916.1045609247, + "ub_ns": 2080661.8885850096, "series": "dynamic_per_shard:4w" }, { "policy": "dynamic_per_worker", "workers": "4w", "load": 100, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_worker_4w/100/new/estimates.json", - "mean_ns": 480978.59250441974, - "lb_ns": 426663.4850814179, - "ub_ns": 547182.7573886289, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_worker_4w/100/new/estimates.json", + "mean_ns": 82720.19460984405, + "lb_ns": 80265.13880820079, + "ub_ns": 85013.63637643303, "series": "dynamic_per_worker:4w" }, { "policy": "dynamic_per_worker", "workers": "4w", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_worker_4w/1000/new/estimates.json", - "mean_ns": 277423.6160682042, - "lb_ns": 274378.7112326404, - "ub_ns": 280653.77858380805, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_worker_4w/1000/new/estimates.json", + "mean_ns": 269145.4262882412, + "lb_ns": 267643.2452785218, + "ub_ns": 270716.6952927899, "series": "dynamic_per_worker:4w" }, { "policy": "dynamic_per_worker", "workers": "4w", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_worker_4w/10000/new/estimates.json", - "mean_ns": 3532714.3493538103, - "lb_ns": 3196782.458081174, - "ub_ns": 3893028.476573624, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_worker_4w/10000/new/estimates.json", + "mean_ns": 2458767.981679218, + "lb_ns": 2431830.4626230644, + "ub_ns": 2485081.4801595937, "series": "dynamic_per_worker:4w" }, { "policy": "static_per_shard", "workers": "4w", "load": 100, - "path": "target/criterion/parallel_policy_matrix/static_per_shard_4w/100/new/estimates.json", - "mean_ns": 99863.61987207436, - "lb_ns": 98266.36378482977, - "ub_ns": 101794.624786117, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_shard_4w/100/new/estimates.json", + "mean_ns": 95333.15514760232, + "lb_ns": 93113.7308296556, + "ub_ns": 97258.48870542648, "series": "static_per_shard:4w" }, { "policy": "static_per_shard", "workers": "4w", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/static_per_shard_4w/1000/new/estimates.json", - "mean_ns": 296294.6607022254, - "lb_ns": 288343.79662623204, - "ub_ns": 307105.6393947541, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_shard_4w/1000/new/estimates.json", + "mean_ns": 269650.38622411125, + "lb_ns": 265859.6976313062, + "ub_ns": 274080.79757797386, "series": "static_per_shard:4w" }, { "policy": "static_per_shard", "workers": "4w", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/static_per_shard_4w/10000/new/estimates.json", - "mean_ns": 3076581.0265688575, - "lb_ns": 2788832.930038881, - "ub_ns": 3400977.1287433044, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_shard_4w/10000/new/estimates.json", + "mean_ns": 2148653.2520275596, + "lb_ns": 2138426.575497818, + "ub_ns": 2161918.422214712, "series": "static_per_shard:4w" }, { "policy": "static_per_worker", "workers": "4w", "load": 100, - "path": "target/criterion/parallel_policy_matrix/static_per_worker_4w/100/new/estimates.json", - "mean_ns": 82828.97430229129, - "lb_ns": 79154.03257528166, - "ub_ns": 87389.61768361439, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_worker_4w/100/new/estimates.json", + "mean_ns": 85693.75888195686, + "lb_ns": 81635.89547608625, + "ub_ns": 90858.99007148478, "series": "static_per_worker:4w" }, { "policy": "static_per_worker", "workers": "4w", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/static_per_worker_4w/1000/new/estimates.json", - "mean_ns": 380211.0759995546, - "lb_ns": 327855.16356549604, - "ub_ns": 462963.92953876726, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_worker_4w/1000/new/estimates.json", + "mean_ns": 268564.7102928172, + "lb_ns": 266324.27978645184, + "ub_ns": 271084.6914134021, "series": "static_per_worker:4w" }, { "policy": "static_per_worker", "workers": "4w", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/static_per_worker_4w/10000/new/estimates.json", - "mean_ns": 4262819.759565299, - "lb_ns": 3869786.074998774, - "ub_ns": 4673047.668490899, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_worker_4w/10000/new/estimates.json", + "mean_ns": 3206786.311422422, + "lb_ns": 3139226.577300076, + "ub_ns": 3283546.0661479966, "series": "static_per_worker:4w" }, + { + "policy": "adaptive_shard_routing", + "workers": "8w", + "load": 100, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/adaptive_shard_routing_8w/100/new/estimates.json", + "mean_ns": 43819.54628046417, + "lb_ns": 43166.04445047363, + "ub_ns": 44580.08270134314, + "series": "adaptive_shard_routing:8w" + }, + { + "policy": "adaptive_shard_routing", + "workers": "8w", + "load": 1000, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/adaptive_shard_routing_8w/1000/new/estimates.json", + "mean_ns": 256792.8897156936, + "lb_ns": 254714.91544597084, + "ub_ns": 259197.7477121638, + "series": "adaptive_shard_routing:8w" + }, + { + "policy": "adaptive_shard_routing", + "workers": "8w", + "load": 10000, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/adaptive_shard_routing_8w/10000/new/estimates.json", + "mean_ns": 2173624.512901018, + "lb_ns": 2129268.373132189, + "ub_ns": 2245384.703926147, + "series": "adaptive_shard_routing:8w" + }, { "policy": "dynamic_per_shard", "workers": "8w", "load": 100, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_shard_8w/100/new/estimates.json", - "mean_ns": 152460.101521985, - "lb_ns": 142689.2895253969, - "ub_ns": 169578.32318578326, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_shard_8w/100/new/estimates.json", + "mean_ns": 133795.5036887287, + "lb_ns": 132276.8768406486, + "ub_ns": 135442.22730167577, "series": "dynamic_per_shard:8w" }, { "policy": "dynamic_per_shard", "workers": "8w", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_shard_8w/1000/new/estimates.json", - "mean_ns": 427597.4980816598, - "lb_ns": 380942.18165343726, - "ub_ns": 493478.6946695924, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_shard_8w/1000/new/estimates.json", + "mean_ns": 297774.60289632913, + "lb_ns": 295708.6289778309, + "ub_ns": 299966.1937386982, "series": "dynamic_per_shard:8w" }, { "policy": "dynamic_per_shard", "workers": "8w", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_shard_8w/10000/new/estimates.json", - "mean_ns": 2876309.416375992, - "lb_ns": 2594111.144678711, - "ub_ns": 3223226.433645327, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_shard_8w/10000/new/estimates.json", + "mean_ns": 2030293.3045370576, + "lb_ns": 2001206.9470137611, + "ub_ns": 2075557.9387499983, "series": "dynamic_per_shard:8w" }, { "policy": "dynamic_per_worker", "workers": "8w", "load": 100, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_worker_8w/100/new/estimates.json", - "mean_ns": 157455.9425359909, - "lb_ns": 153942.67719904362, - "ub_ns": 161920.5141127526, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_worker_8w/100/new/estimates.json", + "mean_ns": 139248.40499947855, + "lb_ns": 138302.44265018118, + "ub_ns": 140180.32400259675, "series": "dynamic_per_worker:8w" }, { "policy": "dynamic_per_worker", "workers": "8w", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_worker_8w/1000/new/estimates.json", - "mean_ns": 339257.17203846463, - "lb_ns": 315584.75279452157, - "ub_ns": 380663.61674345355, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_worker_8w/1000/new/estimates.json", + "mean_ns": 303603.5268193162, + "lb_ns": 301275.8952717267, + "ub_ns": 306547.41233089875, "series": "dynamic_per_worker:8w" }, { "policy": "dynamic_per_worker", "workers": "8w", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/dynamic_per_worker_8w/10000/new/estimates.json", - "mean_ns": 2621356.7823611028, - "lb_ns": 2493971.8226580755, - "ub_ns": 2774790.902435505, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dynamic_per_worker_8w/10000/new/estimates.json", + "mean_ns": 2410652.0441942727, + "lb_ns": 2357525.106032831, + "ub_ns": 2475379.634806578, "series": "dynamic_per_worker:8w" }, { "policy": "static_per_shard", "workers": "8w", "load": 100, - "path": "target/criterion/parallel_policy_matrix/static_per_shard_8w/100/new/estimates.json", - "mean_ns": 236985.7440476028, - "lb_ns": 221566.6802469599, - "ub_ns": 256156.75997772816, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_shard_8w/100/new/estimates.json", + "mean_ns": 143593.84642857304, + "lb_ns": 142229.020591156, + "ub_ns": 144972.96260986192, "series": "static_per_shard:8w" }, { "policy": "static_per_shard", "workers": "8w", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/static_per_shard_8w/1000/new/estimates.json", - "mean_ns": 477808.37468245544, - "lb_ns": 403653.5950145256, - "ub_ns": 583335.7173446632, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_shard_8w/1000/new/estimates.json", + "mean_ns": 303380.14734754537, + "lb_ns": 296138.84317634377, + "ub_ns": 311892.02679463895, "series": "static_per_shard:8w" }, { "policy": "static_per_shard", "workers": "8w", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/static_per_shard_8w/10000/new/estimates.json", - "mean_ns": 2710449.0420398023, - "lb_ns": 2546788.7868638574, - "ub_ns": 2953026.784321096, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_shard_8w/10000/new/estimates.json", + "mean_ns": 2204615.765817444, + "lb_ns": 2147099.942796843, + "ub_ns": 2281943.0792045547, "series": "static_per_shard:8w" }, { "policy": "static_per_worker", "workers": "8w", "load": 100, - "path": "target/criterion/parallel_policy_matrix/static_per_worker_8w/100/new/estimates.json", - "mean_ns": 172220.2781279374, - "lb_ns": 158988.24858006404, - "ub_ns": 188894.3418611982, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_worker_8w/100/new/estimates.json", + "mean_ns": 143419.6752150025, + "lb_ns": 142763.8567366873, + "ub_ns": 144065.49710132796, "series": "static_per_worker:8w" }, { "policy": "static_per_worker", "workers": "8w", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/static_per_worker_8w/1000/new/estimates.json", - "mean_ns": 332053.05171778303, - "lb_ns": 323383.93442205345, - "ub_ns": 341832.6875972533, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_worker_8w/1000/new/estimates.json", + "mean_ns": 297637.2193190274, + "lb_ns": 295349.1741728578, + "ub_ns": 299886.3417154078, "series": "static_per_worker:8w" }, { "policy": "static_per_worker", "workers": "8w", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/static_per_worker_8w/10000/new/estimates.json", - "mean_ns": 5234556.768329204, - "lb_ns": 4974722.401272965, - "ub_ns": 5536259.659252154, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/static_per_worker_8w/10000/new/estimates.json", + "mean_ns": 3172582.2009885465, + "lb_ns": 3153921.8751012925, + "ub_ns": 3191573.5800891295, "series": "static_per_worker:8w" }, { "policy": "dedicated_per_shard", "workers": "dedicated", "load": 100, - "path": "target/criterion/parallel_policy_matrix/dedicated_per_shard/100/new/estimates.json", - "mean_ns": 1911916.2158310344, - "lb_ns": 1770192.7824185104, - "ub_ns": 2076102.2267788248, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dedicated_per_shard/100/new/estimates.json", + "mean_ns": 1268411.098896694, + "lb_ns": 1255724.2592244358, + "ub_ns": 1280124.9725391867, "series": "dedicated_per_shard:dedicated" }, { "policy": "dedicated_per_shard", "workers": "dedicated", "load": 1000, - "path": "target/criterion/parallel_policy_matrix/dedicated_per_shard/1000/new/estimates.json", - "mean_ns": 5056303.960415298, - "lb_ns": 4869380.740892483, - "ub_ns": 5269361.096465565, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dedicated_per_shard/1000/new/estimates.json", + "mean_ns": 4032806.370468118, + "lb_ns": 3995719.371896648, + "ub_ns": 4071979.791524504, "series": "dedicated_per_shard:dedicated" }, { "policy": "dedicated_per_shard", "workers": "dedicated", "load": 10000, - "path": "target/criterion/parallel_policy_matrix/dedicated_per_shard/10000/new/estimates.json", - "mean_ns": 7810389.708333333, - "lb_ns": 7603201.088333334, - "ub_ns": 8024619.369652779, + "path": "/tmp/echo-target-adaptive-bench/criterion/parallel_policy_matrix/dedicated_per_shard/10000/new/estimates.json", + "mean_ns": 5629944.445910836, + "lb_ns": 5562940.938172808, + "ub_ns": 5707613.640982967, "series": "dedicated_per_shard:dedicated" } ] diff --git a/docs/benchmarks/report-inline.html b/docs/benchmarks/report-inline.html index 166d1c2f..4b79cf40 100644 --- a/docs/benchmarks/report-inline.html +++ b/docs/benchmarks/report-inline.html @@ -2811,183 +2811,159 @@

Raw policy table

})(); - +