From a8ffc9267f9cdb24b2551822fd479962c981921a Mon Sep 17 00:00:00 2001 From: "J. Kirby Ross" Date: Sun, 2 Nov 2025 01:39:47 -0800 Subject: [PATCH 01/11] docs: regen rollup after benches update --- crates/rmg-benches/Cargo.toml | 3 + crates/rmg-benches/benches/snapshot_hash.rs | 64 +++++++++++++++++++++ docs/echo-total.md | 6 +- docs/math-validation-plan.md | 6 +- 4 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 crates/rmg-benches/benches/snapshot_hash.rs diff --git a/crates/rmg-benches/Cargo.toml b/crates/rmg-benches/Cargo.toml index 068e3b11..3ead5817 100644 --- a/crates/rmg-benches/Cargo.toml +++ b/crates/rmg-benches/Cargo.toml @@ -12,3 +12,6 @@ rmg-core = { path = "../rmg-core" } name = "motion_throughput" harness = false +[[bench]] +name = "snapshot_hash" +harness = false diff --git a/crates/rmg-benches/benches/snapshot_hash.rs b/crates/rmg-benches/benches/snapshot_hash.rs new file mode 100644 index 00000000..63e9fcca --- /dev/null +++ b/crates/rmg-benches/benches/snapshot_hash.rs @@ -0,0 +1,64 @@ +#![allow(missing_docs)] +use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; +use rmg_core::{ + make_edge_id, make_node_id, make_type_id, EdgeRecord, Engine, GraphStore, NodeRecord, +}; + +fn build_chain_engine(n: usize) -> Engine { + let mut store = GraphStore::default(); + let root = make_node_id("root"); + let world = make_type_id("world"); + store.insert_node( + root, + NodeRecord { + ty: world, + payload: None, + }, + ); + // Insert N nodes and connect them in a chain so all are reachable. + let entity_ty = make_type_id("entity"); + let mut prev = root; + for i in 0..n { + let id = make_node_id(&format!("ent-{}", i)); + store.insert_node( + id, + NodeRecord { + ty: entity_ty, + payload: None, + }, + ); + let edge_id = make_edge_id(&format!("e-{}-{}", i.saturating_sub(1), i)); + store.insert_edge( + prev, + EdgeRecord { + id: edge_id, + from: prev, + to: id, + ty: make_type_id("link"), + payload: None, + }, + ); + prev = id; + } + Engine::new(store, root) +} + +fn bench_snapshot_hash(c: &mut Criterion) { + let mut group = c.benchmark_group("snapshot_hash"); + for &n in &[10usize, 100, 1_000] { + let engine = build_chain_engine(n); + // Throughput: number of nodes included in the reachable set. + group.throughput(Throughput::Elements(n as u64 + 1)); // +1 for root + group.bench_with_input(BenchmarkId::from_parameter(n), &n, |b, &_n| { + b.iter(|| { + // Hash the reachable graph (engine.snapshot performs state_root hashing). + let snap = engine.snapshot(); + criterion::black_box(snap.hash); + }) + }); + } + group.finish(); +} + +criterion_group!(benches, bench_snapshot_hash); +criterion_main!(benches); diff --git a/docs/echo-total.md b/docs/echo-total.md index c08def47..8d61aff6 100644 --- a/docs/echo-total.md +++ b/docs/echo-total.md @@ -1516,7 +1516,8 @@ Goal: ensure Echo’s math module produces identical results across environments --- ## Tooling -- Rust harness (in `rmg-core/tests/math_validation.rs`) validates scalar/vector/matrix/quaternion + PRNG behaviour against JSON fixtures. + +- Rust harness (in `rmg-core/tests/math_validation.rs`) validates scalar/vector/matrix/quaternion + PRNG behavior against JSON fixtures. - Provide deterministic reference values generated offline (e.g., via high-precision Python or Rust) stored in fixtures. - Next step: mirror the fixtures in Vitest with snapshot-style comparisons for the TypeScript layer. - For cross-environment checks, add Playwright-driven tests that run the same suite in headless Chromium/WebKit (call into math module via bundled script). @@ -1525,6 +1526,7 @@ Goal: ensure Echo’s math module produces identical results across environments --- ## Tolerances + - Float32 comparisons use epsilon `1e-6`. - Trig functions might require looser tolerance `1e-5` depending on environment (document deviations). - Fixed-point exact equality expected (integer comparisons). @@ -1532,6 +1534,7 @@ Goal: ensure Echo’s math module produces identical results across environments --- ## Tasks + - [x] Generate reference fixtures (JSON) for scalar/vector/matrix/quaternion/PRNG cases. - [x] Implement Rust-based validation suite (`cargo test -p rmg-core --test math_validation`). - [ ] Mirror fixtures in Vitest to cover the TypeScript bindings (float32 mode). @@ -1542,6 +1545,7 @@ Goal: ensure Echo’s math module produces identical results across environments --- ## Open Questions + - Should we bundle deterministic trig lookup tables for browsers with inconsistent `Math.sin/cos`? - How to expose failure info to designers (e.g., CLI command to run math diagnostics)? - Do we need wasm acceleration for fixed-point operations (profile results first)? diff --git a/docs/math-validation-plan.md b/docs/math-validation-plan.md index 77fb5462..453392e5 100644 --- a/docs/math-validation-plan.md +++ b/docs/math-validation-plan.md @@ -42,7 +42,8 @@ Goal: ensure Echo’s math module produces identical results across environments --- ## Tooling -- Rust harness (in `rmg-core/tests/math_validation.rs`) validates scalar/vector/matrix/quaternion + PRNG behaviour against JSON fixtures. + +- Rust harness (in `rmg-core/tests/math_validation.rs`) validates scalar/vector/matrix/quaternion + PRNG behavior against JSON fixtures. - Provide deterministic reference values generated offline (e.g., via high-precision Python or Rust) stored in fixtures. - Next step: mirror the fixtures in Vitest with snapshot-style comparisons for the TypeScript layer. - For cross-environment checks, add Playwright-driven tests that run the same suite in headless Chromium/WebKit (call into math module via bundled script). @@ -51,6 +52,7 @@ Goal: ensure Echo’s math module produces identical results across environments --- ## Tolerances + - Float32 comparisons use epsilon `1e-6`. - Trig functions might require looser tolerance `1e-5` depending on environment (document deviations). - Fixed-point exact equality expected (integer comparisons). @@ -58,6 +60,7 @@ Goal: ensure Echo’s math module produces identical results across environments --- ## Tasks + - [x] Generate reference fixtures (JSON) for scalar/vector/matrix/quaternion/PRNG cases. - [x] Implement Rust-based validation suite (`cargo test -p rmg-core --test math_validation`). - [ ] Mirror fixtures in Vitest to cover the TypeScript bindings (float32 mode). @@ -68,6 +71,7 @@ Goal: ensure Echo’s math module produces identical results across environments --- ## Open Questions + - Should we bundle deterministic trig lookup tables for browsers with inconsistent `Math.sin/cos`? - How to expose failure info to designers (e.g., CLI command to run math diagnostics)? - Do we need wasm acceleration for fixed-point operations (profile results first)? From f8ee3c98d683040a70a5e86131c61c94a097ce04 Mon Sep 17 00:00:00 2001 From: "J. Kirby Ross" Date: Sun, 2 Nov 2025 01:52:21 -0800 Subject: [PATCH 02/11] bench(deps): add blake3 dev-dep for deterministic rule id; fmt --- crates/rmg-benches/Cargo.toml | 5 ++ crates/rmg-benches/benches/scheduler_drain.rs | 81 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 crates/rmg-benches/benches/scheduler_drain.rs diff --git a/crates/rmg-benches/Cargo.toml b/crates/rmg-benches/Cargo.toml index 3ead5817..b3a125bb 100644 --- a/crates/rmg-benches/Cargo.toml +++ b/crates/rmg-benches/Cargo.toml @@ -7,6 +7,7 @@ publish = false [dev-dependencies] criterion = { version = "0.5", default-features = false, features = ["html_reports"] } rmg-core = { path = "../rmg-core" } +blake3 = "1" [[bench]] name = "motion_throughput" @@ -15,3 +16,7 @@ harness = false [[bench]] name = "snapshot_hash" harness = false + +[[bench]] +name = "scheduler_drain" +harness = false diff --git a/crates/rmg-benches/benches/scheduler_drain.rs b/crates/rmg-benches/benches/scheduler_drain.rs new file mode 100644 index 00000000..4949163f --- /dev/null +++ b/crates/rmg-benches/benches/scheduler_drain.rs @@ -0,0 +1,81 @@ +#![allow(missing_docs)] +use blake3::Hasher; +use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion, Throughput}; +use rmg_core::{ + make_node_id, make_type_id, ApplyResult, ConflictPolicy, Engine, Footprint, Hash, NodeRecord, + PatternGraph, RewriteRule, +}; + +fn bench_noop_rule() -> RewriteRule { + const NAME: &str = "bench/noop"; + // Deterministic rule id: blake3("rule:" ++ name) + let id: Hash = { + let mut h = Hasher::new(); + h.update(b"rule:"); + h.update(NAME.as_bytes()); + h.finalize().into() + }; + fn matcher(_s: &rmg_core::GraphStore, _n: &rmg_core::NodeId) -> bool { + true + } + fn executor(_s: &mut rmg_core::GraphStore, _n: &rmg_core::NodeId) {} + fn footprint(_s: &rmg_core::GraphStore, _n: &rmg_core::NodeId) -> Footprint { + Footprint::default() + } + RewriteRule { + id, + name: NAME, + left: PatternGraph { nodes: vec![] }, + matcher, + executor, + compute_footprint: footprint, + factor_mask: 0, + conflict_policy: ConflictPolicy::Abort, + join_fn: None, + } +} + +fn build_engine_with_entities(n: usize) -> (Engine, Vec) { + let mut engine = rmg_core::build_motion_demo_engine(); + // Register a no-op rule to isolate scheduler overhead from executor work. + engine + .register_rule(bench_noop_rule()) + .expect("register noop rule"); + + let ty = make_type_id("entity"); + let mut labels = Vec::with_capacity(n); + for i in 0..n { + let label = format!("sched-ent-{}", i); + let id = make_node_id(&label); + engine.insert_node(id, NodeRecord { ty, payload: None }); + labels.push(label); + } + (engine, labels) +} + +fn bench_scheduler_drain(c: &mut Criterion) { + let mut group = c.benchmark_group("scheduler_drain"); + for &n in &[10usize, 100, 1_000] { + group.throughput(Throughput::Elements(n as u64)); + group.bench_with_input(BenchmarkId::from_parameter(n), &n, |b, &n| { + b.iter_batched( + || build_engine_with_entities(n), + |(mut engine, labels)| { + // Apply the no-op rule to all entities, then commit. + let tx = engine.begin(); + for label in &labels { + let id = make_node_id(label); + let res = engine.apply(tx, "bench/noop", &id).expect("apply"); + assert!(matches!(res, ApplyResult::Applied)); + } + let _snap = engine.commit(tx).expect("commit"); + }, + BatchSize::PerIteration, + ) + }); + } + group.finish(); +} + +criterion_group!(benches, bench_scheduler_drain); +criterion_main!(benches); From b4b58e4ac5810959fb1878046e0476abe6afd6ba Mon Sep 17 00:00:00 2001 From: "J. Kirby Ross" Date: Sun, 2 Nov 2025 05:34:29 -0800 Subject: [PATCH 03/11] docs(guard): refresh echo-total rollup --- docs/decision-log.md | 11 +++++++++++ docs/echo-total.md | 22 ++++++++++++++++++++++ docs/execution-plan.md | 11 +++++++++++ 3 files changed, 44 insertions(+) diff --git a/docs/decision-log.md b/docs/decision-log.md index dfc1e399..264e88b9 100644 --- a/docs/decision-log.md +++ b/docs/decision-log.md @@ -190,3 +190,14 @@ The following entries use a heading + bullets format for richer context. - Rationale: Keep CI quiet and align with current cargo-deny schema without weakening enforcement. - Consequence: Same effective policy, no deprecation warnings; future license exceptions remain possible via standard cargo-deny mechanisms. - CI Note: Use `cargo-deny >= 0.14.21` in CI (workflow/container) to avoid schema drift and deprecation surprises. Pin the action/image or the downloaded binary version accordingly. + +## 2025-11-02 — PR-12: Sync with main + merge conflict resolution + +- Context: GitHub continued to show a merge conflict on PR #113 (`echo/pr-12-snapshot-bench`). +- Decision: Merge `origin/main` into the branch (merge commit; no rebase) and resolve the conflict in `crates/rmg-benches/Cargo.toml`. +- Resolution kept: + - `license = "Apache-2.0"`, `blake3 = "1"` in dev-dependencies. + - `rmg-core = { version = "0.1.0", path = "../rmg-core" }` (version-pinned path dep per cargo-deny bans). + - Bench targets: `motion_throughput`, `snapshot_hash`, `scheduler_drain`. +- Rationale: Preserve history with a merge, align benches metadata with workspace policy, and clear PR conflict status. +- Consequence: Branch synced with `main`; local hooks (fmt, clippy, tests, rustdoc) passed; CI Docs Guard satisfied via this log and execution-plan update. diff --git a/docs/echo-total.md b/docs/echo-total.md index 54a0c84a..9631fc11 100644 --- a/docs/echo-total.md +++ b/docs/echo-total.md @@ -260,6 +260,17 @@ This is Codex’s working map for building Echo. Update it relentlessly—each s ## Today’s Intent +> 2025-11-02 — PR-12: Sync with main + benches metadata + +- Target: `echo/pr-12-snapshot-bench` (PR #113). +- Merged `origin/main` into the branch (merge commit, no rebase) to clear GitHub conflict status. +- Resolved `crates/rmg-benches/Cargo.toml` conflict by keeping: + - `license = "Apache-2.0"` and `blake3 = "1"` in dev-dependencies. + - Version-pinned path dep: `rmg-core = { version = "0.1.0", path = "../rmg-core" }`. + - Bench entries: `motion_throughput`, `snapshot_hash`, `scheduler_drain`. +- Benches code present/updated: `crates/rmg-benches/benches/snapshot_hash.rs`, `crates/rmg-benches/benches/scheduler_drain.rs`. +- Scope: benches + metadata only; no runtime changes. Hooks (fmt, clippy, tests, rustdoc) were green locally before push. + > 2025-11-02 — PR-11 hotfix-deterministic-rollup-check - Switch to `echo/hotfix-deterministic-rollup-check`, fetch and merge `origin/main` (merge commit; no rebase). @@ -748,6 +759,17 @@ The following entries use a heading + bullets format for richer context. - Consequence: Same effective policy, no deprecation warnings; future license exceptions remain possible via standard cargo-deny mechanisms. - CI Note: Use `cargo-deny >= 0.14.21` in CI (workflow/container) to avoid schema drift and deprecation surprises. Pin the action/image or the downloaded binary version accordingly. +## 2025-11-02 — PR-12: Sync with main + merge conflict resolution + +- Context: GitHub continued to show a merge conflict on PR #113 (`echo/pr-12-snapshot-bench`). +- Decision: Merge `origin/main` into the branch (merge commit; no rebase) and resolve the conflict in `crates/rmg-benches/Cargo.toml`. +- Resolution kept: + - `license = "Apache-2.0"`, `blake3 = "1"` in dev-dependencies. + - `rmg-core = { version = "0.1.0", path = "../rmg-core" }` (version-pinned path dep per cargo-deny bans). + - Bench targets: `motion_throughput`, `snapshot_hash`, `scheduler_drain`. +- Rationale: Preserve history with a merge, align benches metadata with workspace policy, and clear PR conflict status. +- Consequence: Branch synced with `main`; local hooks (fmt, clippy, tests, rustdoc) passed; CI Docs Guard satisfied via this log and execution-plan update. + --- diff --git a/docs/execution-plan.md b/docs/execution-plan.md index 93eaf535..3e900727 100644 --- a/docs/execution-plan.md +++ b/docs/execution-plan.md @@ -33,6 +33,17 @@ This is Codex’s working map for building Echo. Update it relentlessly—each s ## Today’s Intent +> 2025-11-02 — PR-12: Sync with main + benches metadata + +- Target: `echo/pr-12-snapshot-bench` (PR #113). +- Merged `origin/main` into the branch (merge commit, no rebase) to clear GitHub conflict status. +- Resolved `crates/rmg-benches/Cargo.toml` conflict by keeping: + - `license = "Apache-2.0"` and `blake3 = "1"` in dev-dependencies. + - Version-pinned path dep: `rmg-core = { version = "0.1.0", path = "../rmg-core" }`. + - Bench entries: `motion_throughput`, `snapshot_hash`, `scheduler_drain`. +- Benches code present/updated: `crates/rmg-benches/benches/snapshot_hash.rs`, `crates/rmg-benches/benches/scheduler_drain.rs`. +- Scope: benches + metadata only; no runtime changes. Hooks (fmt, clippy, tests, rustdoc) were green locally before push. + > 2025-11-02 — PR-11 hotfix-deterministic-rollup-check - Switch to `echo/hotfix-deterministic-rollup-check`, fetch and merge `origin/main` (merge commit; no rebase). From 748f9607419834b9cea4756b46b8a06c7042941a Mon Sep 17 00:00:00 2001 From: "J. Kirby Ross" Date: Sun, 2 Nov 2025 05:45:03 -0800 Subject: [PATCH 04/11] bench(deps): pin blake3 = 1.8.2 in rmg-benches (cargo-deny policy) --- crates/rmg-benches/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rmg-benches/Cargo.toml b/crates/rmg-benches/Cargo.toml index 116d44f4..9b26dd1c 100644 --- a/crates/rmg-benches/Cargo.toml +++ b/crates/rmg-benches/Cargo.toml @@ -9,7 +9,7 @@ license = "Apache-2.0" criterion = { version = "0.5", default-features = false, features = ["html_reports"] } # Pin version alongside path to satisfy cargo-deny wildcard bans rmg-core = { version = "0.1.0", path = "../rmg-core" } -blake3 = "1" +blake3 = "1.8.2" [[bench]] name = "motion_throughput" From ab56f24331bc41245af073b22ca6f6482483e6e3 Mon Sep 17 00:00:00 2001 From: "J. Kirby Ross" Date: Sun, 2 Nov 2025 05:45:15 -0800 Subject: [PATCH 05/11] bench(snapshot_hash): precompute link type id and fix edge labels e-i-(i+1) --- crates/rmg-benches/benches/snapshot_hash.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/rmg-benches/benches/snapshot_hash.rs b/crates/rmg-benches/benches/snapshot_hash.rs index 63e9fcca..9beed5c4 100644 --- a/crates/rmg-benches/benches/snapshot_hash.rs +++ b/crates/rmg-benches/benches/snapshot_hash.rs @@ -17,6 +17,7 @@ fn build_chain_engine(n: usize) -> Engine { ); // Insert N nodes and connect them in a chain so all are reachable. let entity_ty = make_type_id("entity"); + let link_ty = make_type_id("link"); let mut prev = root; for i in 0..n { let id = make_node_id(&format!("ent-{}", i)); @@ -27,14 +28,14 @@ fn build_chain_engine(n: usize) -> Engine { payload: None, }, ); - let edge_id = make_edge_id(&format!("e-{}-{}", i.saturating_sub(1), i)); + let edge_id = make_edge_id(&format!("e-{}-{}", i, i + 1)); store.insert_edge( prev, EdgeRecord { id: edge_id, from: prev, to: id, - ty: make_type_id("link"), + ty: link_ty, payload: None, }, ); From 1e85eada6db7a685d303be95f39ed334f47b7b0e Mon Sep 17 00:00:00 2001 From: "J. Kirby Ross" Date: Sun, 2 Nov 2025 05:45:32 -0800 Subject: [PATCH 06/11] bench(scheduler_drain): return Vec; avoid re-hashing make_node_id in loop --- crates/rmg-benches/benches/scheduler_drain.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/crates/rmg-benches/benches/scheduler_drain.rs b/crates/rmg-benches/benches/scheduler_drain.rs index 4949163f..9c2fbd76 100644 --- a/crates/rmg-benches/benches/scheduler_drain.rs +++ b/crates/rmg-benches/benches/scheduler_drain.rs @@ -2,8 +2,8 @@ use blake3::Hasher; use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion, Throughput}; use rmg_core::{ - make_node_id, make_type_id, ApplyResult, ConflictPolicy, Engine, Footprint, Hash, NodeRecord, - PatternGraph, RewriteRule, + make_node_id, make_type_id, ApplyResult, ConflictPolicy, Engine, Footprint, Hash, NodeId, + NodeRecord, PatternGraph, RewriteRule, }; fn bench_noop_rule() -> RewriteRule { @@ -35,7 +35,7 @@ fn bench_noop_rule() -> RewriteRule { } } -fn build_engine_with_entities(n: usize) -> (Engine, Vec) { +fn build_engine_with_entities(n: usize) -> (Engine, Vec) { let mut engine = rmg_core::build_motion_demo_engine(); // Register a no-op rule to isolate scheduler overhead from executor work. engine @@ -43,14 +43,14 @@ fn build_engine_with_entities(n: usize) -> (Engine, Vec) { .expect("register noop rule"); let ty = make_type_id("entity"); - let mut labels = Vec::with_capacity(n); + let mut ids = Vec::with_capacity(n); for i in 0..n { let label = format!("sched-ent-{}", i); let id = make_node_id(&label); engine.insert_node(id, NodeRecord { ty, payload: None }); - labels.push(label); + ids.push(id); } - (engine, labels) + (engine, ids) } fn bench_scheduler_drain(c: &mut Criterion) { @@ -60,12 +60,11 @@ fn bench_scheduler_drain(c: &mut Criterion) { group.bench_with_input(BenchmarkId::from_parameter(n), &n, |b, &n| { b.iter_batched( || build_engine_with_entities(n), - |(mut engine, labels)| { + |(mut engine, ids)| { // Apply the no-op rule to all entities, then commit. let tx = engine.begin(); - for label in &labels { - let id = make_node_id(label); - let res = engine.apply(tx, "bench/noop", &id).expect("apply"); + for id in &ids { + let res = engine.apply(tx, "bench/noop", id).expect("apply"); assert!(matches!(res, ApplyResult::Applied)); } let _snap = engine.commit(tx).expect("commit"); From f54d4a213ad72172c1b5b78011689bf9e09d4ac8 Mon Sep 17 00:00:00 2001 From: "J. Kirby Ross" Date: Sun, 2 Nov 2025 05:45:45 -0800 Subject: [PATCH 07/11] docs: refresh echo-total rollup for PR-113 --- docs/echo-total.md | 7 +++++++ docs/execution-plan.md | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/docs/echo-total.md b/docs/echo-total.md index 9631fc11..3740058a 100644 --- a/docs/echo-total.md +++ b/docs/echo-total.md @@ -260,6 +260,13 @@ This is Codex’s working map for building Echo. Update it relentlessly—each s ## Today’s Intent +> 2025-11-02 — PR-12: benches polish and rollup refresh + +- Pin `blake3` in benches to `1.8.2` to satisfy cargo-deny wildcard policy. +- snapshot_hash bench: precompute `link` type id and fix edge labels to `e-i-(i+1)`. +- scheduler_drain bench: return `Vec` from builder and avoid re-hashing node ids in the apply loop. +- Regenerated `docs/echo-total.md` after doc updates. + > 2025-11-02 — PR-12: Sync with main + benches metadata - Target: `echo/pr-12-snapshot-bench` (PR #113). diff --git a/docs/execution-plan.md b/docs/execution-plan.md index 3e900727..1cb480b8 100644 --- a/docs/execution-plan.md +++ b/docs/execution-plan.md @@ -33,6 +33,13 @@ This is Codex’s working map for building Echo. Update it relentlessly—each s ## Today’s Intent +> 2025-11-02 — PR-12: benches polish and rollup refresh + +- Pin `blake3` in benches to `1.8.2` to satisfy cargo-deny wildcard policy. +- snapshot_hash bench: precompute `link` type id and fix edge labels to `e-i-(i+1)`. +- scheduler_drain bench: return `Vec` from builder and avoid re-hashing node ids in the apply loop. +- Regenerated `docs/echo-total.md` after doc updates. + > 2025-11-02 — PR-12: Sync with main + benches metadata - Target: `echo/pr-12-snapshot-bench` (PR #113). From 7e9dbdffe2d887bd8aa870275e53c1d8572ae53c Mon Sep 17 00:00:00 2001 From: "J. Kirby Ross" Date: Sun, 2 Nov 2025 05:47:36 -0800 Subject: [PATCH 08/11] docs(guard): record PR-12 benches pin and micro-optimizations; refresh rollup --- docs/decision-log.md | 10 ++++++++++ docs/echo-total.md | 17 +++++++++++++++++ docs/execution-plan.md | 7 +++++++ 3 files changed, 34 insertions(+) diff --git a/docs/decision-log.md b/docs/decision-log.md index 264e88b9..76ee5312 100644 --- a/docs/decision-log.md +++ b/docs/decision-log.md @@ -191,6 +191,16 @@ The following entries use a heading + bullets format for richer context. - Consequence: Same effective policy, no deprecation warnings; future license exceptions remain possible via standard cargo-deny mechanisms. - CI Note: Use `cargo-deny >= 0.14.21` in CI (workflow/container) to avoid schema drift and deprecation surprises. Pin the action/image or the downloaded binary version accordingly. +## 2025-11-02 — PR-12: benches pin + micro-optimizations + +- Context: CI cargo-deny flagged wildcard policy and benches had minor inefficiencies. +- Decision: + - Pin `blake3` in `crates/rmg-benches/Cargo.toml` to `1.8.2` (no wildcard). + - `snapshot_hash`: compute `link` type id once; label edges as `e-i-(i+1)` (no `e-0-0`). + - `scheduler_drain`: builder returns `Vec`; `apply` loop uses precomputed ids to avoid re-hashing. +- Rationale: Keep dependency policy strict and make benches reflect best practices (no redundant hashing or id recomputation). +- Consequence: Cleaner dependency audit and slightly leaner bench setup without affecting runtime code. + ## 2025-11-02 — PR-12: Sync with main + merge conflict resolution - Context: GitHub continued to show a merge conflict on PR #113 (`echo/pr-12-snapshot-bench`). diff --git a/docs/echo-total.md b/docs/echo-total.md index 3740058a..b5a98b7d 100644 --- a/docs/echo-total.md +++ b/docs/echo-total.md @@ -260,6 +260,13 @@ This is Codex’s working map for building Echo. Update it relentlessly—each s ## Today’s Intent +> 2025-11-02 — PR-12: benches updates (CI docs guard) + +- Dependency policy: pin `blake3` in `rmg-benches` to `1.8.2` (no wildcard). +- snapshot_hash bench: precompute `link` type id once; fix edge labels to `e-i-(i+1)`. +- scheduler_drain bench: builder returns `Vec` to avoid re-hashing labels; bench loop uses the precomputed ids. +- Regenerated `docs/echo-total.md` to reflect these changes. + > 2025-11-02 — PR-12: benches polish and rollup refresh - Pin `blake3` in benches to `1.8.2` to satisfy cargo-deny wildcard policy. @@ -766,6 +773,16 @@ The following entries use a heading + bullets format for richer context. - Consequence: Same effective policy, no deprecation warnings; future license exceptions remain possible via standard cargo-deny mechanisms. - CI Note: Use `cargo-deny >= 0.14.21` in CI (workflow/container) to avoid schema drift and deprecation surprises. Pin the action/image or the downloaded binary version accordingly. +## 2025-11-02 — PR-12: benches pin + micro-optimizations + +- Context: CI cargo-deny flagged wildcard policy and benches had minor inefficiencies. +- Decision: + - Pin `blake3` in `crates/rmg-benches/Cargo.toml` to `1.8.2` (no wildcard). + - `snapshot_hash`: compute `link` type id once; label edges as `e-i-(i+1)` (no `e-0-0`). + - `scheduler_drain`: builder returns `Vec`; `apply` loop uses precomputed ids to avoid re-hashing. +- Rationale: Keep dependency policy strict and make benches reflect best practices (no redundant hashing or id recomputation). +- Consequence: Cleaner dependency audit and slightly leaner bench setup without affecting runtime code. + ## 2025-11-02 — PR-12: Sync with main + merge conflict resolution - Context: GitHub continued to show a merge conflict on PR #113 (`echo/pr-12-snapshot-bench`). diff --git a/docs/execution-plan.md b/docs/execution-plan.md index 1cb480b8..717e9893 100644 --- a/docs/execution-plan.md +++ b/docs/execution-plan.md @@ -33,6 +33,13 @@ This is Codex’s working map for building Echo. Update it relentlessly—each s ## Today’s Intent +> 2025-11-02 — PR-12: benches updates (CI docs guard) + +- Dependency policy: pin `blake3` in `rmg-benches` to `1.8.2` (no wildcard). +- snapshot_hash bench: precompute `link` type id once; fix edge labels to `e-i-(i+1)`. +- scheduler_drain bench: builder returns `Vec` to avoid re-hashing labels; bench loop uses the precomputed ids. +- Regenerated `docs/echo-total.md` to reflect these changes. + > 2025-11-02 — PR-12: benches polish and rollup refresh - Pin `blake3` in benches to `1.8.2` to satisfy cargo-deny wildcard policy. From b6b58b524300099991b834cc912a39dd26dd8c57 Mon Sep 17 00:00:00 2001 From: "J. Kirby Ross" Date: Sun, 2 Nov 2025 06:03:59 -0800 Subject: [PATCH 09/11] bench: restore allow(missing_docs) for criterion macro helpers in benches --- crates/rmg-benches/Cargo.toml | 4 +- crates/rmg-benches/benches/scheduler_drain.rs | 41 ++++++++--- crates/rmg-benches/benches/snapshot_hash.rs | 68 +++++++++++++------ 3 files changed, 82 insertions(+), 31 deletions(-) diff --git a/crates/rmg-benches/Cargo.toml b/crates/rmg-benches/Cargo.toml index 9b26dd1c..90b57637 100644 --- a/crates/rmg-benches/Cargo.toml +++ b/crates/rmg-benches/Cargo.toml @@ -4,12 +4,14 @@ version = "0.1.0" edition = "2021" publish = false license = "Apache-2.0" +description = "Microbenchmarks for Echo (rmg-core): snapshot hashing and scheduler throughput" [dev-dependencies] criterion = { version = "0.5", default-features = false, features = ["html_reports"] } # Pin version alongside path to satisfy cargo-deny wildcard bans rmg-core = { version = "0.1.0", path = "../rmg-core" } -blake3 = "1.8.2" +# Minor-pin for semver compatibility; benches do not rely on a specific patch. +blake3 = "1.8" [[bench]] name = "motion_throughput" diff --git a/crates/rmg-benches/benches/scheduler_drain.rs b/crates/rmg-benches/benches/scheduler_drain.rs index 9c2fbd76..49402927 100644 --- a/crates/rmg-benches/benches/scheduler_drain.rs +++ b/crates/rmg-benches/benches/scheduler_drain.rs @@ -1,4 +1,14 @@ #![allow(missing_docs)] +//! Benchmark: scheduler drain throughput with a no-op rule +//! +//! Applies a trivial no-op rule across `n` entity nodes to measure scheduler +//! overhead rather than executor work. Construction happens in the setup phase; +//! measurement covers applying the rule to each node and committing a tx. +//! +//! Throughput "elements" are rule applications (`n`). +//! BatchSize::PerIteration ensures engine construction is excluded from timing. +//! +//! TODO(PR-14/15): Persist JSON artifacts and add a regression gate. use blake3::Hasher; use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion, Throughput}; use rmg_core::{ @@ -6,13 +16,18 @@ use rmg_core::{ NodeRecord, PatternGraph, RewriteRule, }; +// Bench constants to avoid magic strings. +const BENCH_NOOP_RULE_NAME: &str = "bench/noop"; +const RULE_ID_PREFIX: &[u8] = b"rule:"; +const ENTITY_TYPE_STR: &str = "entity"; +const ENT_LABEL_PREFIX: &str = "sched-ent-"; + fn bench_noop_rule() -> RewriteRule { - const NAME: &str = "bench/noop"; // Deterministic rule id: blake3("rule:" ++ name) let id: Hash = { let mut h = Hasher::new(); - h.update(b"rule:"); - h.update(NAME.as_bytes()); + h.update(RULE_ID_PREFIX); + h.update(BENCH_NOOP_RULE_NAME.as_bytes()); h.finalize().into() }; fn matcher(_s: &rmg_core::GraphStore, _n: &rmg_core::NodeId) -> bool { @@ -24,7 +39,7 @@ fn bench_noop_rule() -> RewriteRule { } RewriteRule { id, - name: NAME, + name: BENCH_NOOP_RULE_NAME, left: PatternGraph { nodes: vec![] }, matcher, executor, @@ -40,12 +55,12 @@ fn build_engine_with_entities(n: usize) -> (Engine, Vec) { // Register a no-op rule to isolate scheduler overhead from executor work. engine .register_rule(bench_noop_rule()) - .expect("register noop rule"); + .expect("Failed to register benchmark noop rule"); - let ty = make_type_id("entity"); + let ty = make_type_id(ENTITY_TYPE_STR); let mut ids = Vec::with_capacity(n); for i in 0..n { - let label = format!("sched-ent-{}", i); + let label = format!("{}{}", ENT_LABEL_PREFIX, i); let id = make_node_id(&label); engine.insert_node(id, NodeRecord { ty, payload: None }); ids.push(id); @@ -56,6 +71,7 @@ fn build_engine_with_entities(n: usize) -> (Engine, Vec) { fn bench_scheduler_drain(c: &mut Criterion) { let mut group = c.benchmark_group("scheduler_drain"); for &n in &[10usize, 100, 1_000] { + // Throughput: number of rule applications in this run (n entities). group.throughput(Throughput::Elements(n as u64)); group.bench_with_input(BenchmarkId::from_parameter(n), &n, |b, &n| { b.iter_batched( @@ -64,10 +80,15 @@ fn bench_scheduler_drain(c: &mut Criterion) { // Apply the no-op rule to all entities, then commit. let tx = engine.begin(); for id in &ids { - let res = engine.apply(tx, "bench/noop", id).expect("apply"); - assert!(matches!(res, ApplyResult::Applied)); + let res = engine + .apply(tx, BENCH_NOOP_RULE_NAME, id) + .expect("Failed to apply noop bench rule"); + // Avoid affecting timing; check only in debug builds. + debug_assert!(matches!(res, ApplyResult::Applied)); } - let _snap = engine.commit(tx).expect("commit"); + let snap = engine.commit(tx).expect("Failed to commit benchmark tx"); + // Ensure the commit work is not optimized away. + criterion::black_box(snap); }, BatchSize::PerIteration, ) diff --git a/crates/rmg-benches/benches/snapshot_hash.rs b/crates/rmg-benches/benches/snapshot_hash.rs index 9beed5c4..67004798 100644 --- a/crates/rmg-benches/benches/snapshot_hash.rs +++ b/crates/rmg-benches/benches/snapshot_hash.rs @@ -1,13 +1,31 @@ #![allow(missing_docs)] -use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; +//! Benchmark: snapshot hash over a linear chain graph +//! +//! Builds a chain of `n` entities reachable from a single root node and +//! measures the cost of computing the snapshot (state_root) hash over the +//! reachable subgraph. Sizes (10, 100, 1000) provide an order-of-magnitude +//! progression to observe scaling trends without long runtimes. +//! +//! Throughput "elements" are the number of nodes in the reachable set +//! (n entities + 1 root). +//! +//! TODO(PR-14/15): Persist JSON artifacts and add a regression gate. +use criterion::{criterion_group, criterion_main, BatchSize, BenchmarkId, Criterion, Throughput}; use rmg_core::{ make_edge_id, make_node_id, make_type_id, EdgeRecord, Engine, GraphStore, NodeRecord, }; +// String constants to avoid magic literals drifting silently. +const ROOT_ID_STR: &str = "root"; +const WORLD_TYPE_STR: &str = "world"; +const ENTITY_TYPE_STR: &str = "entity"; +const LINK_TYPE_STR: &str = "link"; +const ENT_LABEL_PREFIX: &str = "ent-"; + fn build_chain_engine(n: usize) -> Engine { let mut store = GraphStore::default(); - let root = make_node_id("root"); - let world = make_type_id("world"); + let root = make_node_id(ROOT_ID_STR); + let world = make_type_id(WORLD_TYPE_STR); store.insert_node( root, NodeRecord { @@ -16,11 +34,12 @@ fn build_chain_engine(n: usize) -> Engine { }, ); // Insert N nodes and connect them in a chain so all are reachable. - let entity_ty = make_type_id("entity"); - let link_ty = make_type_id("link"); - let mut prev = root; + let entity_ty = make_type_id(ENTITY_TYPE_STR); + let link_ty = make_type_id(LINK_TYPE_STR); + let mut chain_tail = root; for i in 0..n { - let id = make_node_id(&format!("ent-{}", i)); + let to_label = format!("{}{}", ENT_LABEL_PREFIX, i); + let id = make_node_id(&to_label); store.insert_node( id, NodeRecord { @@ -28,18 +47,24 @@ fn build_chain_engine(n: usize) -> Engine { payload: None, }, ); - let edge_id = make_edge_id(&format!("e-{}-{}", i, i + 1)); + // Human-friendly edge id: -to-. + let from_label = if i == 0 { + ROOT_ID_STR.to_string() + } else { + format!("{}{}", ENT_LABEL_PREFIX, i - 1) + }; + let edge_id = make_edge_id(&format!("edge-{}-to-{}", from_label, to_label)); store.insert_edge( - prev, + chain_tail, EdgeRecord { id: edge_id, - from: prev, + from: chain_tail, to: id, ty: link_ty, payload: None, }, ); - prev = id; + chain_tail = id; } Engine::new(store, root) } @@ -47,15 +72,18 @@ fn build_chain_engine(n: usize) -> Engine { fn bench_snapshot_hash(c: &mut Criterion) { let mut group = c.benchmark_group("snapshot_hash"); for &n in &[10usize, 100, 1_000] { - let engine = build_chain_engine(n); - // Throughput: number of nodes included in the reachable set. - group.throughput(Throughput::Elements(n as u64 + 1)); // +1 for root - group.bench_with_input(BenchmarkId::from_parameter(n), &n, |b, &_n| { - b.iter(|| { - // Hash the reachable graph (engine.snapshot performs state_root hashing). - let snap = engine.snapshot(); - criterion::black_box(snap.hash); - }) + // Throughput: total nodes in reachable set (n entities + 1 root). + group.throughput(Throughput::Elements(n as u64 + 1)); + group.bench_with_input(BenchmarkId::from_parameter(n), &n, |b, &n| { + // Build engine in setup (not timed) and measure only hashing. + b.iter_batched( + || build_chain_engine(n), + |engine| { + let snap = engine.snapshot(); + criterion::black_box(snap.hash); + }, + BatchSize::SmallInput, + ) }); } group.finish(); From c0ec43f4146b0dd15f3271d6d3d93d00caeceaf3 Mon Sep 17 00:00:00 2001 From: "J. Kirby Ross" Date: Sun, 2 Nov 2025 06:04:26 -0800 Subject: [PATCH 10/11] bench: snapshot_hash/scheduler_drain polish per review; docs guard updates + rollup --- docs/decision-log.md | 7 +++++++ docs/echo-total.md | 13 +++++++++++++ docs/execution-plan.md | 6 ++++++ 3 files changed, 26 insertions(+) diff --git a/docs/decision-log.md b/docs/decision-log.md index 76ee5312..ea87c85a 100644 --- a/docs/decision-log.md +++ b/docs/decision-log.md @@ -201,6 +201,13 @@ The following entries use a heading + bullets format for richer context. - Rationale: Keep dependency policy strict and make benches reflect best practices (no redundant hashing or id recomputation). - Consequence: Cleaner dependency audit and slightly leaner bench setup without affecting runtime code. +## 2025-11-02 — PR-12: benches constants + documentation + +- Context: Pedantic review flagged magic strings, ambiguous labels, and unclear throughput semantics in benches. +- Decision: Extract constants for ids/types; clarify edge ids as `-to-`; switch `snapshot_hash` to `iter_batched`; add module-level docs and comments on throughput and BatchSize; replace exact blake3 patch pin with minor pin `1.8` and document rationale. +- Rationale: Improve maintainability and readability of performance documentation while keeping timings representative. +- Consequence: Benches read as executable docs; CI docs guard updated accordingly. + ## 2025-11-02 — PR-12: Sync with main + merge conflict resolution - Context: GitHub continued to show a merge conflict on PR #113 (`echo/pr-12-snapshot-bench`). diff --git a/docs/echo-total.md b/docs/echo-total.md index b5a98b7d..1e4bb55c 100644 --- a/docs/echo-total.md +++ b/docs/echo-total.md @@ -267,6 +267,12 @@ This is Codex’s working map for building Echo. Update it relentlessly—each s - scheduler_drain bench: builder returns `Vec` to avoid re-hashing labels; bench loop uses the precomputed ids. - Regenerated `docs/echo-total.md` to reflect these changes. +> 2025-11-02 — PR-12: benches polish (constants + docs) + +- snapshot_hash: extract all magic strings to constants; clearer edge ids using `-to-` labels; use `iter_batched` to avoid redundant inputs; explicit throughput semantics. +- scheduler_drain: DRY rule name/id prefix constants; use `debug_assert!` inside hot path; black_box the post-commit snapshot; added module docs and clarified BatchSize rationale. +- blake3 minor pin: set `blake3 = "1.8"` (semver-compatible); benches don't require an exact patch. + > 2025-11-02 — PR-12: benches polish and rollup refresh - Pin `blake3` in benches to `1.8.2` to satisfy cargo-deny wildcard policy. @@ -783,6 +789,13 @@ The following entries use a heading + bullets format for richer context. - Rationale: Keep dependency policy strict and make benches reflect best practices (no redundant hashing or id recomputation). - Consequence: Cleaner dependency audit and slightly leaner bench setup without affecting runtime code. +## 2025-11-02 — PR-12: benches constants + documentation + +- Context: Pedantic review flagged magic strings, ambiguous labels, and unclear throughput semantics in benches. +- Decision: Extract constants for ids/types; clarify edge ids as `-to-`; switch `snapshot_hash` to `iter_batched`; add module-level docs and comments on throughput and BatchSize; replace exact blake3 patch pin with minor pin `1.8` and document rationale. +- Rationale: Improve maintainability and readability of performance documentation while keeping timings representative. +- Consequence: Benches read as executable docs; CI docs guard updated accordingly. + ## 2025-11-02 — PR-12: Sync with main + merge conflict resolution - Context: GitHub continued to show a merge conflict on PR #113 (`echo/pr-12-snapshot-bench`). diff --git a/docs/execution-plan.md b/docs/execution-plan.md index 717e9893..436f73f4 100644 --- a/docs/execution-plan.md +++ b/docs/execution-plan.md @@ -40,6 +40,12 @@ This is Codex’s working map for building Echo. Update it relentlessly—each s - scheduler_drain bench: builder returns `Vec` to avoid re-hashing labels; bench loop uses the precomputed ids. - Regenerated `docs/echo-total.md` to reflect these changes. +> 2025-11-02 — PR-12: benches polish (constants + docs) + +- snapshot_hash: extract all magic strings to constants; clearer edge ids using `-to-` labels; use `iter_batched` to avoid redundant inputs; explicit throughput semantics. +- scheduler_drain: DRY rule name/id prefix constants; use `debug_assert!` inside hot path; black_box the post-commit snapshot; added module docs and clarified BatchSize rationale. +- blake3 minor pin: set `blake3 = "1.8"` (semver-compatible); benches don't require an exact patch. + > 2025-11-02 — PR-12: benches polish and rollup refresh - Pin `blake3` in benches to `1.8.2` to satisfy cargo-deny wildcard policy. From c44c8272714ec5f4e516f4825a4c927077e3f0e6 Mon Sep 17 00:00:00 2001 From: "J. Kirby Ross" Date: Sun, 2 Nov 2025 06:29:05 -0800 Subject: [PATCH 11/11] docs(rollup): refresh echo-total after benches README + links --- README.md | 2 +- crates/rmg-benches/benches/README.md | 65 ++++++++++++++++++++++++++++ docs/decision-log.md | 7 +++ docs/echo-total.md | 13 ++++++ docs/execution-plan.md | 6 +++ 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 crates/rmg-benches/benches/README.md diff --git a/README.md b/README.md index 8d4616be..e4dc57be 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ It’s the core of the Echo engine: runtime, assets, networking, and tools all o - Command: `cargo bench -p rmg-benches` - Purpose: Runs Criterion micro-benchmarks for the benches crate (`crates/rmg-benches`). -- Location: see `crates/rmg-benches/` for sources and configuration. +- Docs: see `crates/rmg-benches/benches/README.md` for details, tips, and report paths. ### Core Principles diff --git a/crates/rmg-benches/benches/README.md b/crates/rmg-benches/benches/README.md new file mode 100644 index 00000000..27eb1dfa --- /dev/null +++ b/crates/rmg-benches/benches/README.md @@ -0,0 +1,65 @@ +# Echo Benches (rmg-benches) + +This crate hosts Criterion microbenchmarks for Echo’s Rust core (`rmg-core`). + +Benchmarks are executable documentation of performance. Each bench includes +module-level docs describing what is measured, why, and how to interpret +results. This README summarizes how to run them and read the output. + +## What’s Here + +- `snapshot_hash.rs` + - Builds a linear chain of `n` entities reachable from `root` and measures + the snapshot (state_root) hash of the reachable subgraph. + - Throughput “elements” = nodes in the reachable set (`n` entities + 1 root). + - Sizes: `10`, `100`, `1000` to show order-of-magnitude scaling without long + runtimes. + +- `scheduler_drain.rs` + - Registers a trivial no-op rule and applies it to `n` entity nodes within a + transaction to focus on scheduler overhead (not executor work). + - Throughput “elements” = rule applications (`n`). Uses `BatchSize::PerIteration` + so engine construction is excluded from timing. + +## Run + +Run the full benches suite: + +``` +cargo bench -p rmg-benches +``` + +Run a single bench target (faster dev loop): + +``` +cargo bench -p rmg-benches --bench snapshot_hash +cargo bench -p rmg-benches --bench scheduler_drain +``` + +Criterion HTML reports are written under `target/criterion//report/index.html`. + +## Interpreting Results + +- Use the throughput value to sanity‑check the scale of work per iteration. +- The primary signal is `time/iter` across inputs (e.g., 10 vs 100 vs 1000). +- For regressions, compare runs in `target/criterion` or host an artifact in CI + (planned for PR‑14/15) and gate on percent deltas. + +## Environment Notes + +- Toolchain: `stable` Rust (see `rust-toolchain.toml`). +- Dependency policy: avoid wildcards; benches use a minor pin for `blake3`. +- Repro: keep your machine under minimal background load; prefer `--quiet` and + close other apps. + +## Flamegraphs (optional) + +If you have [`inferno`](https://github.com/jonhoo/inferno) or `cargo-flamegraph` +installed, you can profile a bench locally. Example (may require sudo on Linux): + +``` +cargo flamegraph -p rmg-benches --bench snapshot_hash -- --sample-size 50 +``` + +These tools are not required for CI and are optional for local analysis. + diff --git a/docs/decision-log.md b/docs/decision-log.md index ea87c85a..9f005a5a 100644 --- a/docs/decision-log.md +++ b/docs/decision-log.md @@ -208,6 +208,13 @@ The following entries use a heading + bullets format for richer context. - Rationale: Improve maintainability and readability of performance documentation while keeping timings representative. - Consequence: Benches read as executable docs; CI docs guard updated accordingly. +## 2025-11-02 — PR-12: benches README + main link + +- Context: Missing documentation for how to run/interpret Criterion benches. +- Decision: Add `crates/rmg-benches/benches/README.md` and link from the top-level `README.md`. +- Rationale: Improve discoverability and ensure new contributors can reproduce measurements. +- Consequence: Docs Guard satisfied; single-source guidance for bench usage and outputs. + ## 2025-11-02 — PR-12: Sync with main + merge conflict resolution - Context: GitHub continued to show a merge conflict on PR #113 (`echo/pr-12-snapshot-bench`). diff --git a/docs/echo-total.md b/docs/echo-total.md index 1e4bb55c..3de3cf86 100644 --- a/docs/echo-total.md +++ b/docs/echo-total.md @@ -273,6 +273,12 @@ This is Codex’s working map for building Echo. Update it relentlessly—each s - scheduler_drain: DRY rule name/id prefix constants; use `debug_assert!` inside hot path; black_box the post-commit snapshot; added module docs and clarified BatchSize rationale. - blake3 minor pin: set `blake3 = "1.8"` (semver-compatible); benches don't require an exact patch. +> 2025-11-02 — PR-12: benches README + +- Added `crates/rmg-benches/benches/README.md` documenting how to run and interpret + benchmarks, report locations, and optional flamegraph usage. +- Linked it from the main `README.md`. + > 2025-11-02 — PR-12: benches polish and rollup refresh - Pin `blake3` in benches to `1.8.2` to satisfy cargo-deny wildcard policy. @@ -796,6 +802,13 @@ The following entries use a heading + bullets format for richer context. - Rationale: Improve maintainability and readability of performance documentation while keeping timings representative. - Consequence: Benches read as executable docs; CI docs guard updated accordingly. +## 2025-11-02 — PR-12: benches README + main link + +- Context: Missing documentation for how to run/interpret Criterion benches. +- Decision: Add `crates/rmg-benches/benches/README.md` and link from the top-level `README.md`. +- Rationale: Improve discoverability and ensure new contributors can reproduce measurements. +- Consequence: Docs Guard satisfied; single-source guidance for bench usage and outputs. + ## 2025-11-02 — PR-12: Sync with main + merge conflict resolution - Context: GitHub continued to show a merge conflict on PR #113 (`echo/pr-12-snapshot-bench`). diff --git a/docs/execution-plan.md b/docs/execution-plan.md index 436f73f4..2014045f 100644 --- a/docs/execution-plan.md +++ b/docs/execution-plan.md @@ -46,6 +46,12 @@ This is Codex’s working map for building Echo. Update it relentlessly—each s - scheduler_drain: DRY rule name/id prefix constants; use `debug_assert!` inside hot path; black_box the post-commit snapshot; added module docs and clarified BatchSize rationale. - blake3 minor pin: set `blake3 = "1.8"` (semver-compatible); benches don't require an exact patch. +> 2025-11-02 — PR-12: benches README + +- Added `crates/rmg-benches/benches/README.md` documenting how to run and interpret + benchmarks, report locations, and optional flamegraph usage. +- Linked it from the main `README.md`. + > 2025-11-02 — PR-12: benches polish and rollup refresh - Pin `blake3` in benches to `1.8.2` to satisfy cargo-deny wildcard policy.