From 44fe4384fc42ae5405af9866d1ff528f17691a4f Mon Sep 17 00:00:00 2001 From: Brummel Date: Sun, 10 May 2026 12:11:40 +0200 Subject: [PATCH] design-md-consolidation 1.5: condense historical bench data-points in DESIGN.md --- docs/DESIGN.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/docs/DESIGN.md b/docs/DESIGN.md index a653200..90da520 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -831,14 +831,14 @@ is too. ## Decision 10: memory model — RC + Uniqueness with LLM-author annotations **The GC bench (`bench/run.sh`) showed -Boehm contributing ~60% of runtime on allocation-heavy workloads -that hold the heap fully live. Sharpened later the same day: the +Boehm contributing a substantial fraction of runtime on allocation-heavy workloads +that hold the heap fully live (bench notes in JOURNAL). Sharpened later the same day: the mainstream "RC + inference" position was extended with mandatory LLM-author mode annotations (`borrow` / `own`), explicit `clone`, first-class `reuse-as`, and `drop-iterative` data attrs.** The cost of GC is structurally in the allocate path — Boehm's -`GC_malloc` is ~2.8× slower than a bump pointer, and the bench +`GC_malloc` is structurally slower than a bump pointer, and the bench workloads exercised allocate cost without collection cost. Tracing GC's irreducible variability cannot be tuned away; RC's costs are bounded and analysable per program point. A corpus @@ -860,8 +860,7 @@ amortises against one allocation. The corpus was later extended with `bench_closure_chain` (closure-pair allocation: each step allocates *two* heap objects, the closure cell and its captured env struct) and `bench_hof_pipeline` (poly-ADT + indirect -dispatch). The closure-chain fixture's measured `rc/bump = 4.14×` -reflects the doubled allocation tax on closure construction — +dispatch). The closure-chain fixture measures wider than the 1.3× linear/tree target — the doubled allocation tax on closure construction is reflected (current ratio recorded in JOURNAL bench entries) — each step pays two allocs and two decs against one bump-pointer bump. This is a representational cost of the closure-pair layout, not a defect in the RC implementation; a future slab/pool @@ -870,8 +869,7 @@ follow-up) would compress this ratio without changing semantics. The 1.3× retirement target therefore applies to the linear / tree / poly-ADT subset of the corpus. Closure-heavy workloads are -tracked under a wider band (the 21'g baseline records `4.14×` -as the `rc_over_bump` reference value with ±15% tolerance) and +tracked under a wider band (the closure-chain baseline records its rc/bump ratio as the `rc_over_bump` reference value with ±15% tolerance, recorded in JOURNAL bench entries) and are explicitly excluded from the Boehm-retirement gate until a slab/pool answer ships. Decision-10's RC commitment is unchanged; what is scoped is the *quantitative* retirement criterion, not @@ -894,8 +892,7 @@ closures + match). ### Why not other memory models -**Tracing GC.** Open-ended. Boehm's bench number (~60% allocate- -path overhead) is structural; tuning Boehm cannot move that +**Tracing GC.** Open-ended. Boehm's bench overhead is structurally on the allocate path (JOURNAL bench notes); tuning Boehm cannot move that needle. A precise tracing GC would need read/write barriers, root maps, generational machinery — months of work, with irreducible pause-time variability at the end. The user's @@ -1607,12 +1604,12 @@ indirect-jump cost. A mono-vs-vdisp micro-benchmark (`bench/mono_dispatch.py`, JOURNAL bench-notes entry) refutes that specific claim: on a saturating branch predictor with a monomorphic indirect target, indirect dispatch is free relative to -the same-shape non-inlined direct call (1.000x on Zen 3 / clang -O2). +the same-shape non-inlined direct call. The correct rationale is one level up: **mono makes the call target visible to the optimiser, unlocking inlining and downstream loop transformations that virtual dispatch prevents in principle.** The -measured end-to-end win on a tight LCG hot loop is 3.31x vs -non-inlinable direct call and 4.00x vs polymorphic vdisp (4 distinct +measured end-to-end win on a tight LCG hot loop is substantial vs +non-inlinable direct call and larger again vs polymorphic vdisp (4 distinct targets cycling). On larger callee bodies or cold call sites the inlining win shrinks toward zero, but the architectural claim — "mono enables optimisations vdisp forbids" — holds across the spectrum,