Orchestrata Ultimate › Plans › suite-runtime-2-plan

Suite runtime, attempt 2 — plan

Source: plans/suite-runtime-2-plan.md at 8a2cb42ad · last changed 2026-08-12 · first committed 2026-08-12 · 182 lines.

Prose pending.

Plan text

Suite runtime, attempt 2 — plan

Date: 2026-08-12 Baseline: 6ceef2ef + uncommitted D2b fix — 426.6s wall, 32,499 passed / 0 failed / 0 errors / 0 skipped, 1611/1611 modules, -j 8 -b 6. Call CPU 2,202.4s, 8-lane floor 275.3s. Success: lower total suite wall, proven at suite scale, with test count non-decreasing and 0 failures. Nothing else counts.

This plan is bound by plans/suite-runtime-failure-postmortem-2026-08-12.md §7. Attempt 1 failed because it optimized module-local costs that did not transfer to a saturated 8-lane run, and measured the result with a design that could not detect a win of the available size. Every lever below carries its share of the lane budget, and the measurement design comes first.


1. Measured structure of the 426.6s (this tree, not last week's)

Component Lane-seconds Share of the 3,413 lane-s budget
Test-call CPU 2,202.4s 64.5%
Non-call lane time (idle + collect + import + fixture + teardown) 1,210.6s 35.5%

The headline structural fact: the suite runs 8 lanes on a 12-core machine and leaves 35% of even that reduced budget idle. Lane count is the only lever that touches 100% of the wall.

1b. Lane-budget decomposition — MEASURED, not inferred (2026-08-12)

Each component measured directly rather than left as a residual. This replaces attempt 1's WEAK 793s/397s split, which was cache-minus-call arithmetic.

Component Lane-seconds Share How measured
Test-call time 2,202.4s 65.1% durations sink, 05:16 run
Fixture setup/teardown 516.7s measured 15.3% JUnit per-batch setup+teardown sum
Unattributed ~321s 9.5% residual − the measured fixture sum (see below)
Tail idle 268s 7.9% 5s-bucket occupancy curve
Process startup (51 × 1.22s) 62s 1.8% pytest --collect-only on one tiny module = 1.22s
Collection/import, ALL 1611 modules 12s 0.4% pytest tests/ --collect-only = 11.74s total

Correction, 2026-08-12 (second review). This table previously assigned the whole ~837s residual to "fixture setup/teardown", which contradicted §3c's independently-measured 516.7 lane-s for the same bucket, in the same document. The residual is not a measurement: it is everything the four measured terms do not explain, and only 516.7s of it is measured fixture cost. ~321 lane-s remain unattributed and no number in this plan may be derived from them. Two further defects in the same arithmetic, both open:

What settles all three: test_executor._process_batch_result already parses every batch's JUnit XML — the only source that separates setup/call/teardown — and then deletes it. Retaining those rows, keyed by run/batch/lane, converts the weakest number in this decomposition into a measured one at zero extra parsing cost. See plans/prolog-learning-subsystem-research-2026-08-12.md.

Two hypotheses died here. Per-batch fixed cost is 1.22s, not the ~23s the two-configuration arithmetic suggested — so batch-count reduction is not a lever, and neither is import cost: collecting the entire tree costs 11.74s. The non-call time is fixture setup/teardown, nothing else.

1c. Is the slow work CPU or waiting? — MEASURED

The 40 slowest tests (638.5s of call time) run in one process: WALL 162.75s, USER 127.26s, SYS 10.09s → 84% CPU. They are CPU-bound. Consequences:

1d. Lane count — MEASURED AND REJECTED

config wall call time failures solo retries
-j 8 -b 6 (baseline) 426.6s 2,202.4s 0 1
-j 12 -b 6 410.0s 2,982.5s (+35.4%) 0 0

17s of wall is inside the noise band (identical trees have measured 426.6s and 445.7s), while the CPU inflation is unambiguous: load reached 16.05 on 12 cores and every test ran slower. L1 is rejected — not on one run's wall, but on the mechanism the CPU number exposes.

1e. The suite is already at its physical-core floor — MEASURED

Full run under /usr/bin/time (includes every waited-for child process, which matters because many tests shell out):

wall 489.15s | user 2368.77s | sys 198.93s | cpu 524% | maxrss 3.4GB
32,499 passed / 0 failed / 0 errors / 0 skipped · 1611/1611 modules · batch phase 455s

The suite is sitting ON its floor. Average utilisation is 524% ≈ 5.2 of 6 physical cores, which is also why -j 12 inflated per-test wall by 35%: at 8 lanes the physical cores are already busy, and the extra lanes contend for hyperthread siblings.

Consequence, and it governs everything below: the ONLY change that lowers suite wall on this machine is one that lowers total core-seconds. Scheduling, batching, lane count, fixture scope, and work relocation cannot — they redistribute the same 2,568 core-seconds. This is the mechanism behind attempt 1's "contention laundering", stated as arithmetic instead of a metaphor.

3b. Primary metric upgrade — core-seconds, not wall

Wall is the goal but a poor instrument: identical trees measured 426.6s and 455s (6.6% apart). Total core-seconds (user + sys from /usr/bin/time around the whole run) is the primary acceptance metric — it is near-deterministic, it is what actually causes wall on a core-bound suite, and a change that does not reduce it cannot reduce wall except by luck.

2. Lever inventory — each with its floor mass

Any lever below the ~5% noise floor needs the measurement design in §3 written down before work starts (post-mortem rule 3).

# Lever Floor mass Touches test quality?
L1 Lane count 8 → 12 8-lane floor 275.3s → 12-lane floor 183.5s. Affects 100% of the wall. No — config only
L2 Per-batch fixed cost (51 batches × spawn + collect + import) To be measured; at 10s/batch it is 510 lane-s = 15% of budget No
L3 Tail packing (--backfill, duration-aware bin fill) ≤268 idle lane-s ≈ 33s wall (7.7%) No
L4 Redundant work inside the ≥1s cut (532 tests, 1,579.5s) Per-item, must be ELIMINATION not relocation Must not reduce coverage
L5 Import cost per batch (package + test-module imports) Subset of L2; measured separately No

Ruled out before starting, with reasons: resident workers (measured +32%, reverted, see the post-mortem); pytest-xdist (banned, deadlocks); reducing test count, scope, or assertions in any form.

3. Measurement design — fixed before any change

Noise is the reason attempt 1 could not tell a win from a quiet machine: identical trees measured 445.7s and 426.6s (4.5% apart) and call CPU has ranged 24% across days.

3c. Measured ceiling — stated before the work, not after

Lever Mass Wall equivalent at 6 cores
Fixture setup/teardown, whole suite 516.7 lane-s (~279 core-s) 47s if eliminated entirely; ~18s at a realistic 50% of the top 100
Top-24 heavy modules 499.6 core-s 83s if eliminated entirely; ~21s at a realistic 25%
Lane count 8 → 12 one run: 426.6s → 410.0s ~16s, pending n=3

Ceiling ≈ 10–15% — 427s to roughly 370–385s. Not a halving. The suite's CPU is spread across 32,499 tests doing real work against real infrastructure; there is no single big win, and any claim of one should be treated as an error. This number is stated before the work starts, per the post-mortem's rule 4 (no estimates before decomposition; premise shrink is disclosed).

4. Execution

L1 is a configuration probe and needs no swarm; it is measured first because it is the largest lever and it can invalidate the rest. L2/L3/L5 are code work and are swarmed only with a measured floor mass in hand. L4 is entered only if L1-L3 fall short, and only for work that is genuinely eliminated rather than moved.

Definition of finished (user, 2026-08-12): merged, promoted, deployed, worktree deleted. A lever that does not survive §3 does not merge.

5. Results

Filled in as runs complete. Verdict first, table second.