Skip to content

fix(protocol): keep keyed subscription families sharing when sharing saves most of the work (#378) - #385

Merged
jsam merged 4 commits into
mainfrom
fm/fix-keyed-regress
Oct 5, 2026
Merged

jsam merged 4 commits into
mainfrom
fm/fix-keyed-regress

Conversation

@jsam

@jsam jsam commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Intent

I want you to really hyper focus on making the symbolic engine, you know, crisp and really truly production ready. (Context: #378 : a write at 1M edges with 1,000 keyed subscriptions now costs 11.9 s CPU and a 643 ms ack, against 0.18 s and 3.8 ms before. Measured by the views benchmark from PR #369 (branch fm/m9-v1-benches, make bench-views-remote).)

Substance of the referenced issue #378 and benchmark: the views benchmark (PR #369, perf-gate views) reproduces the architecture review's baseline on the review's commit within noise, but current main regressed keyed rule-view sharing: N subscribers each subscribed to their own key ?r1(head_i, Y) of the deployed rule r1(X,Y) <- edge(X,Y), label(X,"hot"), each write changing one key's result; at 1M edges with 1,000 keys one write costs 11.9 s CPU and a 643 ms ack, against 0.18 s and 3.8 ms before. Suspects merged since: #355 (session throughput, round dedup), #303 (shared probe round fix), #282 (parameterised programs). Bisect on the benchmark host, then fix or revert the culprit; add this case to the perf gate so it can never regress silently again.

What Changed

  • In src/protocol/subscription/parameterized.rs, keeps_sharing now has a second way to accept a shared round. Before, a round passed only if it was no slower than the views' own evaluations running in parallel on the compute permits. Now it also passes if it does at most half of the views' combined work and is at most twice as slow as those parallel evaluations. When a family stops sharing, it records its binding count, and it probes again as soon as that count doubles, so a verdict reached while views were still subscribing is not kept for the many that join later. New unit tests cover the new thresholds, overflow, the Regression: keyed rule-view sharing, a write costs 11.9 s CPU and a 643 ms ack at 1M edges / 1,000 keys (was 0.18 s / 3.8 ms) #378 shape (100 keys, 18 permits, 7 ms round), and probing again once bindings double.
  • Added a gated delta_keyed perf-gate fixture (perf-gate/src/fixtures/keyed.rs, plus profile params and a Graph::chains dataset). It runs 300 agents, each subscribed to its own key ?r1(H_k, Y) of r1(X, Y) <- edge(X, Y), label(X, "hot") over 100K edges, and an open-loop writer whose writes each change one key. policy.toml now requires delta_us p50/p99, ack_us p99 and a new writes_per_server_cpu_sec metric. The gate's default fixtures go from eight to nine.
  • Updated the WebSocket API guide, the configuration guide, config.example.toml and the GUI docs bundle to describe the new sharing criteria and the re-probe on doubled bindings.

Bisect and benchmark results

All runs on the benchmark host sam-dev-benchmarks (nproc 32, servers pinned to CPUs 8-31, 18 compute permits), one at a time under the shared lock, with the views benchmark from #369.

Culprit: #304 (0341d8c). Keyed x100 at 100k edges, server CPU per write:

commit CPU ms/write
09e05b3 (architecture review) 45.7
fe9ffe2 (#303) 45.7
edb8bc3 (#294) 45.3
6ac5322 (#333), parent of #304 46.3
0341d8c (#304) 160.3
every later commit to 41f38ef 150.7 - 158.0

#304 made the bound read ?r1(400,Y) about five times cheaper (6.3 to 1.2 ms). The family's latency-only judge then refused to share (logged: shared_us=85445 own_us=9739 bindings=100 permits=18), and its backoff outlasted the 1,000 views that joined later. #304 itself is kept; the judge is fixed.

Issue #378's case (1M edges, keyed 1, 10, 100 then 1,000), keyed x1000:

before #304 (09e05b3) main (67a9782) this PR (1b21544)
server CPU per write 180 ms 11,297 ms 119.5 ms
ack p50 / p99 3.8 / 8.3 ms 590 / 624 ms 3.9 / 4.5 ms
delta p50 / p99 75 / 104 ms 615 / 1,104 ms 77.0 / 80.4 ms

Keyed x100 at 1M: 1,040 ms (main) to 127.5 ms CPU per write. Keyed x100 at 100k: 134.7 to 16.7 ms.

New delta_keyed gate fixture, 6 paired rounds against main: server CPU per write 85 ms to 16-24 ms (PASS); ack p50/p99 equal within noise; all 12 runs delivered every one of the 300 agents exactly its own rows.

Accepted trade (firstmate's decision): against current main, delta_keyed delta p50 rises from about 5.3 to 10.6 ms and p99 from about 11.7 to 16.6 ms (both FAIL), because main evaluates all 300 views in parallel at 6-8 times the CPU. Sharing again costs 3.5-8 times less CPU per write, keeps the tail bounded under load, and matches the delta latency of the commit before #304 (10.5 ms p50 on both). It is capped: a family shares for the work it saves only while a round is at most twice as slow as the views' own evaluations in parallel.

Not fixed here: a fresh family of 1,000 views still re-evaluates every view on its first write before any verdict (cold-start storm, about 745 ms CPU per write averaged over 20 writes at 1M edges, on main and here alike); #304 also made recursive reads 9-20% slower; the approved perf-gate baseline (e732cd5) predates subscription families, so delta_keyed catches sharing regressions only against a merge base.

Risk Assessment

✅ Low: The fix round matches the recorded decision. keeps_sharing now computes shared_us <= min(max(parallel, combined), 2*parallel) with saturating arithmetic. Traced inputs: the 1,000 x 1 ms example on 18 permits gives 112,000 (shares) and 112,001 (stops), so 450 ms stops. The #378 cases still share: 7 ms against 12 ms, and the logged 1M-edge case of 85,445 us against 116,868 us. The overflow assertions also hold. The re-probe when bindings double resets on a rule change and is refreshed at each stop, and the docs and docs bundle describe the new rule consistently.

Testing

As the user decided, this phase records the locked benchmark-host job for exactly head 1b215441 against base 67a9782f as its live validation. It did not rebuild servers or re-run the perf gate. I confirmed the raw results on the host and copied the reports into the evidence directory. - Perf gate, delta_keyed: all 12 runs exited cleanly and delivered every agent's own rows. CPU per write passes at a cost ratio of 0.28. Delta p50 and p99 are FAIL against base: that is the higher idle delta the user accepted in exchange for the CPU savings, now capped at twice the parallel own latency. Ack is INCONCLUSIVE (within noise). - Views benchmark at 1M edges: keyed x1000 server CPU per write falls from 11,297 ms to 119.5 ms. Ack p99 falls from 624 ms to 4.5 ms, and delta p99 from 1,104 ms to 80 ms. Base logs the family stopping sharing; the candidate never does. - Views benchmark at 100k edges: keyed x100 CPU per write falls from 134.7 ms to 16.7 ms. The parameterized-subscription unit tests, including the new 1,000 × 1 ms on 18 permits latency-ceiling case, pass. There is no UI surface, so there are no screenshots. The worktree is clean.

  • Live validation: ✅ go - 4 of 4 scenarios driven live against the product
Scenario Result Live Evidence
300 agents, each subscribed to its own key ?r1(H_k, Y), receive exactly their own inserted row on every write (no wrong, missing or duplicate deltas) ✅ pass live ev-gate_report.md / ev-gate_bench.txt: perf-gate delta_keyed, 6 paired rounds on sam-dev-benchmarks, all 12 fixture runs completed, run exit 0 (the fixture fails a run on any missing, foreign, duplica…
A write to a keyed family costs far less server CPU on the candidate than on base (issue #378 regression gone at 1M edges, 1,000 keys) ✅ pass live e1m summaries: keyed x1000 CPU per write 11297.5 -> 119.5 ms, ack p99 624 -> 4.5 ms; keyed x100 1039.5 -> 127.5 ms; e100 keyed x100 134.7 -> 16.7 ms; perf-gate writes_per_server_cpu_sec PASS at ratio…
The perf gate now covers keyed subscriptions, so the #378 regression cannot recur silently (the gate separates base from candidate on CPU per write) ✅ pass live ev-gate_verdict.json: the delta_keyed fixture produces a PASS/FAIL verdict on writes_per_server_cpu_sec (12 vs 42 writes per CPU second, the base arm regressed)
Keyed delta latency stays bounded on the candidate, and sharing does not make deltas wait more than about twice as long as the views evaluated in parallel ✅ pass live ev-gate_report.md: delta p50 10.6 ms, p99 16.6 ms (bounded; the higher idle delta is the trade the user accepted); e1m keyed x1000 delta p99 80.4 ms vs 1103.9 ms on base; the candidate server log has…
Evidence: perf-gate delta_keyed paired report (base 67a9782 vs candidate 1b21544)
## Performance gate: INVALID

Policy **provisional**: cost budget p50 +5%, p99 +10%, throughput -5%; 95% interval of the median paired per-round ratio. Budgets are the plan's proposed ceilings, pending captain decision D1; tightening is always allowed.

- baseline: `67a9782f` (binary sha256 5425b7cc4951)
- candidate: `1b215441` (binary sha256 1b94d2d22d76)
- profile `standard`, 6 rounds, fixtures delta_keyed
- host `computeinstance-e00nfsdgf9dzq987g3`: AMD EPYC-Genoa Processor (32 CPUs, 125 GB), kernel 6.11.0-1016-nvidia, governor unknown, data on ext4 (~/bench/fix-keyed-regress/results/ev-gate/servers), server CPUs 8-31
- load average: start `2.59 1.60 1.94 1/442 247334`, end `1.28 1.41 1.84 1/453 248693`

\### Problems

- bound_query.concurrent_latency_us.p99: baseline: 0 valid rounds, need 6
- bound_query.latency_us.p50: baseline: 0 valid rounds, need 6
- bound_query.latency_us.p99: baseline: 0 valid rounds, need 6
- bound_query.queries_per_sec: baseline: 0 valid rounds, need 6
- cheap_query.latency_us.p50: baseline: 0 valid rounds, need 6
- cheap_query.latency_us.p99: baseline: 0 valid rounds, need 6
- cheap_query.queries_per_sec: baseline: 0 valid rounds, need 6
- delta_fanout.delta_us.p50: baseline: 0 valid rounds, need 6
- delta_fanout.delta_us.p99: baseline: 0 valid rounds, need 6
- delta_fanout.last_agent_us.p99: baseline: 0 valid rounds, need 6
- delta_first.first_delta_us.p50: baseline: 0 valid rounds, need 6
- delta_first.warm_delta_us.p50: baseline: 0 valid rounds, need 6
- delta_single.delta_us.p50: baseline: 0 valid rounds, need 6
- delta_single.delta_us.p99: baseline: 0 valid rounds, need 6
- insert_batch.ack_us.p50: baseline: 0 valid rounds, need 6
- insert_batch.facts_per_sec: baseline: 0 valid rounds, need 6
- insert_single.ack_us.p50: baseline: 0 valid rounds, need 6
- insert_single.ack_us.p99: baseline: 0 valid rounds, need 6
- insert_single.concurrent_facts_per_sec: baseline: 0 valid rounds, need 6
- insert_single.facts_per_sec: baseline: 0 valid rounds, need 6
- interference.delta_us.p50: baseline: 0 valid rounds, need 6
- interference.delta_us.p99: baseline: 0 valid rounds, need 6

\### Required metrics

| metric | baseline | candidate | cost ratio | interval | budget | baseline spread | status |
|---|---|---|---|---|---|---|---|
| bound_query.concurrent_latency_us.p99 | - | - | - | - | 1.10 | - | INVALID: baseline: 0 valid rounds, need 6 |
| bound_query.latency_us.p50 | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| bound_query.latency_us.p99 | - | - | - | - | 1.10 | - | INVALID: baseline: 0 valid rounds, need 6 |
| bound_query.queries_per_sec | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| cheap_query.latency_us.p50 | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| cheap_query.latency_us.p99 | - | - | - | - | 1.10 | - | INVALID: baseline: 0 valid rounds, need 6 |
| cheap_query.queries_per_sec | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| delta_fanout.delta_us.p50 | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| delta_fanout.delta_us.p99 | - | - | - | - | 1.10 | - | INVALID: baseline: 0 valid rounds, need 6 |
| delta_fanout.last_agent_us.p99 | - | - | - | - | 1.10 | - | INVALID: baseline: 0 valid rounds, need 6 |
| delta_first.first_delta_us.p50 | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| delta_first.warm_delta_us.p50 | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| delta_keyed.ack_us.p99 | 9.753 ms | 10.068 ms | 0.896 | 0.791..1.400 | 1.10 | 36.3% | INCONCLUSIVE |
| delta_keyed.delta_us.p50 | 5.185 ms | 10.607 ms | 2.034 | 1.891..2.121 | 1.05 | 14.5% | FAIL |
| delta_keyed.delta_us.p99 | 11.672 ms | 16.605 ms | 1.310 | 1.207..1.743 | 1.10 | 29.8% | FAIL |
| delta_keyed.writes_per_server_cpu_sec | 0.012 ms | 0.042 ms | 0.283 | 0.191..0.290 | 1.05 | 1.4% | PASS |
| delta_single.delta_us.p50 | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| delta_single.delta_us.p99 | - | - | - | - | 1.10 | - | INVALID: baseline: 0 valid rounds, need 6 |
| insert_batch.ack_us.p50 | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| insert_batch.facts_per_sec | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| insert_single.ack_us.p50 | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| insert_single.ack_us.p99 | - | - | - | - | 1.10 | - | INVALID: baseline: 0 valid rounds, need 6 |
| insert_single.concurrent_facts_per_sec | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| insert_single.facts_per_sec | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| interference.delta_us.p50 | - | - | - | - | 1.05 | - | INVALID: baseline: 0 valid rounds, need 6 |
| interference.delta_us.p99 | - | - | - | - | 1.10 | - | INVALID: baseline: 0 valid rounds, need 6 |

\### Diagnostic metrics (not gated)

| metric | baseline | candidate | cost ratio | interval | budget | baseline spread | status |
|---|---|---|---|---|---|---|---|
| delta_keyed.ack_us.p50 | 3.394 ms | 3.659 ms | 1.064 | 0.942..1.204 | 1.05 | 20.9% | INCONCLUSIVE |
| delta_keyed.subscribe_us.p50 | 2.754 ms | 2.716 ms | 0.983 | 0.976..0.999 | 1.05 | 1.2% | PASS |
| delta_keyed.subscribe_us.p99 | 2.869 ms | 2.853 ms | 0.990 | 0.958..1.009 | 1.10 | 3.3% | PASS |
Evidence: perf-gate delta_keyed verdict
{
  "status": "INVALID",
  "policy_status": "provisional",
  "problems": [
    "bound_query.concurrent_latency_us.p99: baseline: 0 valid rounds, need 6",
    "bound_query.latency_us.p50: baseline: 0 valid rounds, need 6",
    "bound_query.latency_us.p99: baseline: 0 valid rounds, need 6",
    "bound_query.queries_per_sec: baseline: 0 valid rounds, need 6",
    "cheap_query.latency_us.p50: baseline: 0 valid rounds, need 6",
    "cheap_query.latency_us.p99: baseline: 0 valid rounds, need 6",
    "cheap_query.queries_per_sec: baseline: 0 valid rounds, need 6",
    "delta_fanout.delta_us.p50: baseline: 0 valid rounds, need 6",
    "delta_fanout.delta_us.p99: baseline: 0 valid rounds, need 6",
    "delta_fanout.last_agent_us.p99: baseline: 0 valid rounds, need 6",
    "delta_first.first_delta_us.p50: baseline: 0 valid rounds, need 6",
    "delta_first.warm_delta_us.p50: baseline: 0 valid rounds, need 6",
    "delta_single.delta_us.p50: baseline: 0 valid rounds, need 6",
    "delta_single.delta_us.p99: baseline: 0 valid rounds, need 6",
    "insert_batch.ack_us.p50: baseline: 0 valid rounds, need 6",
    "insert_batch.facts_per_sec: baseline: 0 valid rounds, need 6",
    "insert_single.ack_us.p50: baseline: 0 valid rounds, need 6",
    "insert_single.ack_us.p99: baseline: 0 valid rounds, need 6",
    "insert_single.concurrent_facts_per_sec: baseline: 0 valid rounds, need 6",
    "insert_single.facts_per_sec: baseline: 0 valid rounds, need 6",
    "interference.delta_us.p50: baseline: 0 valid rounds, need 6",
    "interference.delta_us.p99: baseline: 0 valid rounds, need 6"
  ],
  "metrics": [
    {
      "metric": "bound_query.concurrent_latency_us.p99",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.1,
      "baseline_spread": null
    },
    {
      "metric": "bound_query.latency_us.p50",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "bound_query.latency_us.p99",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.1,
      "baseline_spread": null
    },
    {
      "metric": "bound_query.queries_per_sec",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "cheap_query.latency_us.p50",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "cheap_query.latency_us.p99",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.1,
      "baseline_spread": null
    },
    {
      "metric": "cheap_query.queries_per_sec",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "delta_fanout.delta_us.p50",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "delta_fanout.delta_us.p99",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.1,
      "baseline_spread": null
    },
    {
      "metric": "delta_fanout.last_agent_us.p99",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.1,
      "baseline_spread": null
    },
    {
      "metric": "delta_first.first_delta_us.p50",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "delta_first.warm_delta_us.p50",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "delta_keyed.ack_us.p50",
      "required": false,
      "status": "INCONCLUSIVE",
      "reason": "interval straddles 1.05: rerun on a quieter host or add rounds",
      "baseline": [
        3292.0,
        3076.0,
        3193.0,
        3784.0,
        3496.0,
        3507.0
      ],
      "candidate": [
        3962.0,
        3064.0,
        3696.0,
        3564.0,
        3623.0,
        3828.0
      ],
      "baseline_median": 3394.0,
      "candidate_median": 3659.5,
      "round_ratios": [
        1.2035236938031593,
        0.9960988296488946,
        1.15753210147197,
        0.9418604651162791,
        1.0363272311212814,
        1.0915312232677503
      ],
      "cost_ratio": 1.063929227194516,
      "interval": [
        0.9418604651162791,
        1.2035236938031593
      ],
      "tolerance": 0.05,
      "baseline_spread": 0.20860341779611077
    },
    {
      "metric": "delta_keyed.ack_us.p99",
      "required": true,
      "status": "INCONCLUSIVE",
      "reason": "interval straddles 1.10: rerun on a quieter host or add rounds",
      "baseline": [
        9847.0,
        8650.0,
        10676.0,
        9659.0,
        11818.0,
        8282.0
      ],
      "candidate": [
        7788.0,
        11828.0,
        9759.0,
        8406.0,
        10376.0,
        11595.0
      ],
      "baseline_median": 9753.0,
      "candidate_median": 10067.5,
      "round_ratios": [
        0.79090078196405,
        1.367398843930636,
        0.9141064068939678,
        0.8702764261310695,
        0.8779827381959723,
        1.400024148756339
      ],
      "cost_ratio": 0.89604457254497,
      "interval": [
        0.79090078196405,
        1.400024148756339
      ],
      "tolerance": 0.1,
 

... [386 bytes truncated] ...

      10604.0,
        10611.0,
        10484.0,
        10700.0
      ],
      "baseline_median": 5185.0,
      "candidate_median": 10607.5,
      "round_ratios": [
        2.1213372664700096,
        2.084756222999383,
        2.094824180165942,
        1.8907697790449038,
        1.9837275307473983,
        1.9489981785063752
      ],
      "cost_ratio": 2.0342418768733905,
      "interval": [
        1.8907697790449038,
        2.1213372664700096
      ],
      "tolerance": 0.05,
      "baseline_spread": 0.14484088717454194
    },
    {
      "metric": "delta_keyed.delta_us.p99",
      "required": true,
      "status": "FAIL",
      "reason": "regression: whole interval above 1.10",
      "baseline": [
        12645.0,
        11394.0,
        11950.0,
        11018.0,
        14029.0,
        10551.0
      ],
      "candidate": [
        15266.0,
        19046.0,
        15416.0,
        14656.0,
        17793.0,
        18391.0
      ],
      "baseline_median": 11672.0,
      "candidate_median": 16604.5,
      "round_ratios": [
        1.2072756030051404,
        1.6715815341407758,
        1.290041841004184,
        1.33018696678163,
        1.2683013757217192,
        1.7430575300919344
      ],
      "cost_ratio": 1.3101144038929071,
      "interval": [
        1.2072756030051404,
        1.7430575300919344
      ],
      "tolerance": 0.1,
      "baseline_spread": 0.29797806716929404
    },
    {
      "metric": "delta_keyed.subscribe_us.p50",
      "required": false,
      "status": "PASS",
      "reason": "interval within 1.05",
      "baseline": [
        2753.0,
        2783.0,
        2755.0,
        2760.0,
        2750.0,
        2753.0
      ],
      "candidate": [
        2686.0,
        2715.0,
        2753.0,
        2757.0,
        2692.0,
        2716.0
      ],
      "baseline_median": 2754.0,
      "candidate_median": 2715.5,
      "round_ratios": [
        0.9756629131856157,
        0.9755659360402443,
        0.9992740471869328,
        0.9989130434782608,
        0.978909090909091,
        0.9865601162368326
      ],
      "cost_ratio": 0.9827346035729618,
      "interval": [
        0.9755659360402443,
        0.9992740471869328
      ],
      "tolerance": 0.05,
      "baseline_spread": 0.011982570806100218
    },
    {
      "metric": "delta_keyed.subscribe_us.p99",
      "required": false,
      "status": "PASS",
      "reason": "interval within 1.10",
      "baseline": [
        2857.0,
        2953.0,
        2889.0,
        2867.0,
        2859.0,
        2872.0
      ],
      "candidate": [
        2883.0,
        2828.0,
        2872.0,
        2891.0,
        2794.0,
        2834.0
      ],
      "baseline_median": 2869.5,
      "candidate_median": 2853.0,
      "round_ratios": [
        1.0091004550227511,
        0.9576701659329495,
        0.9941156109380408,
        1.0083711196372516,
        0.9772647778943686,
        0.9867688022284122
      ],
      "cost_ratio": 0.9904422065832266,
      "interval": [
        0.9576701659329495,
        1.0091004550227511
      ],
      "tolerance": 0.1,
      "baseline_spread": 0.0334553058024046
    },
    {
      "metric": "delta_keyed.writes_per_server_cpu_sec",
      "required": true,
      "status": "PASS",
      "reason": "interval within 1.05",
      "baseline": [
        11.904761904761905,
        11.799410029498524,
        11.892963330029733,
        11.846001974333662,
        11.776251226692835,
        11.741682974559687
      ],
      "candidate": [
        42.40282685512368,
        61.224489795918366,
        41.666666666666664,
        62.17616580310881,
        41.37931034482759,
        40.54054054054054
      ],
      "baseline_median": 11.822706001916092,
      "candidate_median": 42.034746760895175,
      "round_ratios": [
        0.28075396825396826,
        0.1927236971484759,
        0.2854311199207136,
        0.19052319842053306,
        0.28459273797841017,
        0.2896281800391389
      ],
      "cost_ratio": 0.28267335311618924,
      "interval": [
        0.19052319842053306,
        0.2896281800391389
      ],
      "tolerance": 0.05,
      "baseline_spread": 0.013793705956638688
    },
    {
      "metric": "delta_single.delta_us.p50",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "delta_single.delta_us.p99",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.1,
      "baseline_spread": null
    },
    {
      "metric": "insert_batch.ack_us.p50",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "insert_batch.facts_per_sec",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "insert_single.ack_us.p50",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "insert_single.ack_us.p99",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.1,
      "baseline_spread": null
    },
    {
      "metric": "insert_single.concurrent_facts_per_sec",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "insert_single.facts_per_sec",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "interference.delta_us.p50",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.05,
      "baseline_spread": null
    },
    {
      "metric": "interference.delta_us.p99",
      "required": true,
      "status": "INVALID",
      "reason": "baseline: 0 valid rounds, need 6",
      "baseline": [],
      "candidate": [],
      "baseline_median": null,
      "candidate_median": null,
      "round_ratios": [],
      "cost_ratio": null,
      "interval": null,
      "tolerance": 0.1,
      "baseline_spread": null
    }
  ]
}
Evidence: perf-gate run metadata (host, CPUs, command, exit)
host: computeinstance-e00nfsdgf9dzq987g3
nproc: 32
baseline: 67a9782f candidate: 1b215441
command: perf-gate-1b215441 run --fixtures delta_keyed --rounds 6 --server-cpus 8-31 (client on 0-7)
load average at start: 2.59 1.60 1.94 1/442 247332
run exit 0
load average at end: 1.28 1.41 1.84 2/445 248696
Evidence: Views benchmark 1M edges, candidate
# Views: cost of reads and writes against deployed rules

- candidate: 1b215441429a2e49ef8454542b6101df0361ed33 (~/bench/fix-keyed-regress/bin/server-1b215441)
- host computeinstance-e00nfsdgf9dzq987g3 (32 CPUs, server CPUs 8-31), load average 1.28 1.41 1.84 1/446 248715 -> 0.95 1.26 1.73 1/449 249410

## 1000000 edges (candidate)

Load: 1000002 edges, 3334 hot heads in 3016 ms (server CPU 2140 ms), RSS 190 MB. Peak RSS 1184 MB.

Registration: fillers_to_0 0 ms, hot_reach 17 ms, path 7 ms, path_step 7 ms, r1 6 ms.

| read | rules | rows | p50 / p99 ms | server CPU ms/read | rule evaluations/read | view reads/read |
|---|---|---|---|---|---|---|
| `?edge(400,Y)` | 4 | 1 | 5.0 / 5.6 | 6.7 | - | - |
| `?r1(X,Y)` | 4 | 3334 | 69.2 / 70.0 | 66.7 | - | - |
| `?r1(400,Y)` | 4 | 1 | 6.6 / 6.7 | 6.7 | - | - |
| `?path(400,Y)` | 4 | 3 | 3122.5 / 3352.6 | 3183.3 | - | - |
| `?hot_reach(X,Y)` | 4 | 10002 | 3223.2 / 3240.6 | 3226.7 | - | - |
| `?hot_reach(400,Y)` | 4 | 3 | 3190.8 / 3211.6 | 3200.0 | - | - |
| `?r1(X,Y)` | 4 | 3504 | 70.2 / 71.3 | 66.7 | - | - |
| `?r1(400,Y)` | 4 | 9 | 7.0 / 8.6 | 6.7 | - | - |

| phase | subs | ack p50 / p99 ms | write->delta p50 / p99 ms | read during p50 ms | server CPU ms/write | frames/write | rule evaluations/write | maintenance us/write | RSS MB | late |
|---|---|---|---|---|---|---|---|---|---|---|
| P0_no_subs | 0 | 1.9 / 6.1 | - | 6.9 | 7.0 | 0.0 | - | - | 181 | 0 |
| P1_r1_unbound_x1 | 1 | 2.5 / 3.0 | 72.0 / 73.1 | 8.4 | 78.5 | 2.0 | - | - | 184 | 0 |
| P2_r1_unbound_x100 | 100 | 2.7 / 6.9 | 72.9 / 83.1 | 8.5 | 83.0 | 200.0 | - | - | 206 | 0 |
| P3_hot_reach_unbound_x1 | 1 | 2.6 / 7.9 | 3298.8 / 3350.4 | 8.0 | 3307.5 | 2.0 | - | - | 201 | 0 |
| P4_r1_keyed_x1 | 1 | 2.0 / 4.6 | 8.6 / 11.7 | 7.4 | 14.5 | 2.0 | - | - | 203 | 0 |
| P4_r1_keyed_x10 | 10 | 1.9 / 5.6 | 10.1 / 15.5 | 8.0 | 94.5 | 11.0 | - | - | 215 | 0 |
| P4_r1_keyed_x100 | 100 | 2.7 / 4.5 | 73.9 / 77.7 | 8.2 | 127.5 | 101.0 | - | - | 248 | 0 |
| P4_r1_keyed_x1000 | 1000 | 3.9 / 4.5 | 77.0 / 80.4 | 7.7 | 119.5 | 1001.0 | - | - | 276 | 0 |
| P6_r1_unbound_x1_rules4 | 1 | 2.5 / 5.6 | 72.5 / 76.1 | 7.7 | 79.5 | 2.0 | - | - | 278 | 0 |

Subscribe: 1 x `?r1(X,Y)` 74 ms, 100 x `?r1(X,Y)` 167 ms, 1 x `?hot_reach(X,Y)` 3553 ms, 1 x `?r1(0,Y)` 11 ms, 10 x `?r1(0,Y)` 14 ms, 100 x `?r1(0,Y)` 85 ms, 1000 x `?r1(0,Y)` 978 ms, 1 x `?r1(X,Y)` 75 ms.

- the server exports no view work counters; work columns are empty
- hot_reach keyed x1000000 skipped: the graph has 3334 hot heads
Evidence: Views benchmark 1M edges, base
# Views: cost of reads and writes against deployed rules

- candidate: 67a9782fef6d18f36229668e4fbe6392871c0330 (~/bench/fix-keyed-regress/bin/server-67a9782f)
- host computeinstance-e00nfsdgf9dzq987g3 (32 CPUs, server CPUs 8-31), load average 0.95 1.26 1.73 1/441 249428 -> 4.40 1.96 1.89 1/449 250170

## 1000000 edges (candidate)

Load: 1000002 edges, 3334 hot heads in 3080 ms (server CPU 2220 ms), RSS 194 MB. Peak RSS 1179 MB.

Registration: fillers_to_0 0 ms, hot_reach 8 ms, path 7 ms, path_step 8 ms, r1 6 ms.

| read | rules | rows | p50 / p99 ms | server CPU ms/read | rule evaluations/read | view reads/read |
|---|---|---|---|---|---|---|
| `?edge(400,Y)` | 4 | 1 | 5.1 / 5.6 | 6.7 | - | - |
| `?r1(X,Y)` | 4 | 3334 | 69.6 / 71.2 | 70.0 | - | - |
| `?r1(400,Y)` | 4 | 1 | 6.9 / 7.1 | 6.7 | - | - |
| `?path(400,Y)` | 4 | 3 | 3123.3 / 3331.2 | 3160.0 | - | - |
| `?hot_reach(X,Y)` | 4 | 10002 | 3198.9 / 3227.3 | 3206.7 | - | - |
| `?hot_reach(400,Y)` | 4 | 3 | 3164.6 / 3164.7 | 3160.0 | - | - |
| `?r1(X,Y)` | 4 | 3504 | 71.5 / 71.8 | 73.3 | - | - |
| `?r1(400,Y)` | 4 | 9 | 8.8 / 9.4 | 10.0 | - | - |

| phase | subs | ack p50 / p99 ms | write->delta p50 / p99 ms | read during p50 ms | server CPU ms/write | frames/write | rule evaluations/write | maintenance us/write | RSS MB | late |
|---|---|---|---|---|---|---|---|---|---|---|
| P0_no_subs | 0 | 1.8 / 4.3 | - | 7.1 | 7.7 | 0.0 | - | - | 182 | 0 |
| P1_r1_unbound_x1 | 1 | 2.3 / 7.2 | 72.5 / 77.3 | 7.6 | 78.5 | 2.0 | - | - | 186 | 0 |
| P2_r1_unbound_x100 | 100 | 2.6 / 4.1 | 72.0 / 80.9 | 8.7 | 83.0 | 200.0 | - | - | 206 | 0 |
| P3_hot_reach_unbound_x1 | 1 | 2.6 / 3.5 | 3296.5 / 3318.8 | 8.3 | 3301.5 | 2.0 | - | - | 203 | 0 |
| P4_r1_keyed_x1 | 1 | 1.9 / 3.2 | 8.9 / 11.8 | 7.8 | 16.0 | 2.0 | - | - | 205 | 0 |
| P4_r1_keyed_x10 | 10 | 2.0 / 5.6 | 10.5 / 15.9 | 8.1 | 97.0 | 11.0 | - | - | 217 | 0 |
| P4_r1_keyed_x100 | 100 | 3.2 / 41.5 | 34.8 / 94.9 | 41.8 | 1039.5 | 101.0 | - | - | 226 | 0 |
| P4_r1_keyed_x1000 | 1000 | 590.2 / 624.2 | 615.4 / 1103.9 | 12.7 | 11297.5 | 1001.0 | - | - | 262 | 0 |
| P6_r1_unbound_x1_rules4 | 1 | 2.5 / 2.8 | 73.1 / 74.9 | 7.9 | 79.5 | 2.0 | - | - | 275 | 0 |

Subscribe: 1 x `?r1(X,Y)` 73 ms, 100 x `?r1(X,Y)` 182 ms, 1 x `?hot_reach(X,Y)` 3574 ms, 1 x `?r1(0,Y)` 11 ms, 10 x `?r1(0,Y)` 14 ms, 100 x `?r1(0,Y)` 86 ms, 1000 x `?r1(0,Y)` 962 ms, 1 x `?r1(X,Y)` 73 ms.

- the server exports no view work counters; work columns are empty
- hot_reach keyed x1000000 skipped: the graph has 3334 hot heads
Evidence: Views benchmark 100k edges, candidate
# Views: cost of reads and writes against deployed rules

- candidate: 1b215441429a2e49ef8454542b6101df0361ed33 (~/bench/fix-keyed-regress/bin/server-1b215441)
- host computeinstance-e00nfsdgf9dzq987g3 (32 CPUs, server CPUs 8-31), load average 3.33 1.66 1.97 1/443 247188 -> 2.59 1.60 1.94 1/451 247319

## 100000 edges (candidate)

Load: 100002 edges, 334 hot heads in 309 ms (server CPU 220 ms), RSS 45 MB. Peak RSS 144 MB.

Registration: fillers_to_0 0 ms, hot_reach 9 ms, path 8 ms, path_step 8 ms, r1 7 ms.

| read | rules | rows | p50 / p99 ms | server CPU ms/read | rule evaluations/read | view reads/read |
|---|---|---|---|---|---|---|
| `?edge(400,Y)` | 4 | 1 | 0.7 / 1.2 | 0.0 | - | - |
| `?r1(X,Y)` | 4 | 334 | 6.9 / 6.9 | 6.7 | - | - |
| `?r1(400,Y)` | 4 | 1 | 1.1 / 1.1 | 0.0 | - | - |
| `?path(400,Y)` | 4 | 3 | 287.7 / 312.2 | 293.3 | - | - |
| `?hot_reach(X,Y)` | 4 | 1002 | 300.1 / 312.9 | 303.3 | - | - |
| `?hot_reach(400,Y)` | 4 | 3 | 296.5 / 297.9 | 296.7 | - | - |
| `?r1(X,Y)` | 4 | 484 | 7.9 / 8.1 | 6.7 | - | - |
| `?r1(400,Y)` | 4 | 6 | 1.3 / 1.5 | 3.3 | - | - |

| phase | subs | ack p50 / p99 ms | write->delta p50 / p99 ms | read during p50 ms | server CPU ms/write | frames/write | rule evaluations/write | maintenance us/write | RSS MB | late |
|---|---|---|---|---|---|---|---|---|---|---|
| P0_no_subs | 0 | 1.8 / 6.1 | - | 1.2 | 1.3 | 0.0 | - | - | 40 | 0 |
| P1_r1_unbound_x1 | 1 | 2.0 / 2.7 | 8.9 / 9.6 | 1.3 | 9.0 | 2.0 | - | - | 41 | 0 |
| P2_r1_unbound_x100 | 100 | 2.2 / 5.5 | 9.0 / 13.1 | 1.3 | 11.7 | 200.0 | - | - | 45 | 0 |
| P3_hot_reach_unbound_x1 | 1 | 2.4 / 5.8 | 308.9 / 314.5 | 1.8 | 309.0 | 2.0 | - | - | 44 | 0 |
| P4_r1_keyed_x100 | 100 | 2.1 / 5.7 | 9.7 / 13.3 | 1.4 | 16.7 | 101.0 | - | - | 57 | 0 |
| P6_r1_unbound_x1_rules4 | 1 | 2.0 / 7.0 | 9.1 / 14.1 | 1.4 | 9.7 | 2.0 | - | - | 59 | 0 |

Subscribe: 1 x `?r1(X,Y)` 9 ms, 100 x `?r1(X,Y)` 44 ms, 1 x `?hot_reach(X,Y)` 330 ms, 100 x `?r1(0,Y)` 28 ms, 1 x `?r1(X,Y)` 9 ms.

- the server exports no view work counters; work columns are empty
- hot_reach keyed x1000000 skipped: the graph has 334 hot heads
Evidence: Views benchmark 100k edges, base
# Views: cost of reads and writes against deployed rules

- candidate: 67a9782fef6d18f36229668e4fbe6392871c0330 (~/bench/fix-keyed-regress/bin/server-67a9782f)
- host computeinstance-e00nfsdgf9dzq987g3 (32 CPUs, server CPUs 8-31), load average 4.45 1.74 2.00 1/442 247034 -> 3.33 1.66 1.97 1/451 247170

## 100000 edges (candidate)

Load: 100002 edges, 334 hot heads in 326 ms (server CPU 210 ms), RSS 53 MB. Peak RSS 149 MB.

Registration: fillers_to_0 0 ms, hot_reach 8 ms, path 8 ms, path_step 9 ms, r1 7 ms.

| read | rules | rows | p50 / p99 ms | server CPU ms/read | rule evaluations/read | view reads/read |
|---|---|---|---|---|---|---|
| `?edge(400,Y)` | 4 | 1 | 0.7 / 1.2 | 0.0 | - | - |
| `?r1(X,Y)` | 4 | 334 | 6.9 / 7.0 | 6.7 | - | - |
| `?r1(400,Y)` | 4 | 1 | 1.1 / 1.1 | 0.0 | - | - |
| `?path(400,Y)` | 4 | 3 | 287.3 / 314.9 | 296.7 | - | - |
| `?hot_reach(X,Y)` | 4 | 1002 | 302.5 / 303.8 | 300.0 | - | - |
| `?hot_reach(400,Y)` | 4 | 3 | 298.2 / 298.7 | 300.0 | - | - |
| `?r1(X,Y)` | 4 | 484 | 7.8 / 7.9 | 10.0 | - | - |
| `?r1(400,Y)` | 4 | 6 | 1.5 / 1.9 | 0.0 | - | - |

| phase | subs | ack p50 / p99 ms | write->delta p50 / p99 ms | read during p50 ms | server CPU ms/write | frames/write | rule evaluations/write | maintenance us/write | RSS MB | late |
|---|---|---|---|---|---|---|---|---|---|---|
| P0_no_subs | 0 | 1.7 / 2.8 | - | 1.2 | 1.7 | 0.0 | - | - | 45 | 0 |
| P1_r1_unbound_x1 | 1 | 2.0 / 8.4 | 8.9 / 15.3 | 1.3 | 9.0 | 2.0 | - | - | 45 | 0 |
| P2_r1_unbound_x100 | 100 | 2.2 / 2.8 | 9.1 / 10.2 | 1.3 | 11.7 | 200.0 | - | - | 50 | 0 |
| P3_hot_reach_unbound_x1 | 1 | 2.7 / 40.5 | 311.1 / 349.3 | 1.8 | 311.7 | 2.0 | - | - | 49 | 0 |
| P4_r1_keyed_x100 | 100 | 2.6 / 6.3 | 7.1 / 12.7 | 9.0 | 134.7 | 101.0 | - | - | 63 | 0 |
| P6_r1_unbound_x1_rules4 | 1 | 2.1 / 2.7 | 9.2 / 10.2 | 1.4 | 9.0 | 2.0 | - | - | 63 | 0 |

Subscribe: 1 x `?r1(X,Y)` 9 ms, 100 x `?r1(X,Y)` 48 ms, 1 x `?hot_reach(X,Y)` 333 ms, 100 x `?r1(0,Y)` 32 ms, 1 x `?r1(X,Y)` 9 ms.

- the server exports no view work counters; work columns are empty
- hot_reach keyed x1000000 skipped: the graph has 334 hot heads
Evidence: Keyed x1000 at 1M edges, base -> candidate
P4_r1_keyed_x1000 base: ack 590.2/624.2 ms, delta 615.4/1103.9 ms, CPU 11297.5 ms/write
P4_r1_keyed_x1000 cand: ack 3.9/ 4.5 ms, delta 77.0/ 80.4 ms, CPU 119.5 ms/write
delta_keyed.writes_per_server_cpu_sec ratio 0.283 PASS
- Outcome: 🔧 2 issues found → no changes applied ✅ across 2 runs (2m36s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

🔧 **Review** - 1 issue found → auto-fixed ✅
  • ⚠️ src/protocol/subscription/parameterized.rs:110 - The new work criterion in keeps_sharing (shared_us &lt;= max(parallel, own*bindings/2)) puts no ceiling on how much slower a shared round can be than the views' own evaluations run in parallel. Example: 1,000 keyed views at 1 ms each on 18 permits. Parallel own evaluations finish in about 56 ms. The work bound is 500 ms, so a 450 ms round keeps sharing. Every delta in the family then waits roughly 8 times longer while saving only about 55% of the CPU. The commit message accepts a version of this trade (idle delta p50 5.8 to 10.2 ms on delta_keyed). The unbounded case is still a product decision: should sharing also require the round to stay within some multiple of the parallel latency, or should the divisor depend on load? It is flagged because the intent asks for a production-ready engine, and this changes latency behaviour for every keyed family, not only the benchmark's.

🔧 Fix applied.
✅ Re-checked - no issues remain.

🔧 **Test** - 2 issues found → no changes applied ✅
Scenario Result Live Evidence
300 agents each subscribed to their own key ?r1(H_k, Y) receive exactly their own inserted row on every write (no wrong or missing deltas) ⏸️ untested no I started the live perf-gate delta_keyed run, but it was still compiling the base commit's release server when this phase had to report, and I then stopped it. No server ran. Run `make perf-gate-remot…
A write to a keyed family costs far less server CPU on the candidate than on base 67a9782 (writes_per_server_cpu_sec rises, issue #378 regression gone) ⏸️ untested no This needs the paired run of base and candidate, which was stopped while the base server was still compiling. Nothing was measured.
Keyed delta and ack latency (delta_us p50/p99, ack_us p99) stay bounded on the candidate, and sharing does not make deltas wait more than about twice as long as the views evaluated in parallel ⏸️ untested no This comes from the same delta_keyed run, which was stopped before any server ran.
  • scripts/perf-gate.sh --baseline-rev 67a9782fef6d18f36229668e4fbe6392871c0330 --fixtures delta_keyed --rounds 3 --no-verdict --server-cpus 8-31 --gate-cpus 0-7 (started; stopped while compiling the base commit's server; no measurement)
  • Read the diff between 67a9782f and 1b215441: keeps_sharing with SHARED_WORK_DIVISOR and the SHARED_SLOWDOWN latency cap, re-probing once bindings double, and the new delta_keyed fixture added to the policy's required set

🔧 No changes applied.
✅ Re-checked - no issues remain.

  • Live validation: ✅ go - 4 of 4 scenarios driven live against the product
Scenario Result Live Evidence
300 agents, each subscribed to its own key ?r1(H_k, Y), receive exactly their own inserted row on every write (no wrong, missing or duplicate deltas) ✅ pass live ev-gate_report.md / ev-gate_bench.txt: perf-gate delta_keyed, 6 paired rounds on sam-dev-benchmarks, all 12 fixture runs completed, run exit 0 (the fixture fails a run on any missing, foreign, duplica…
A write to a keyed family costs far less server CPU on the candidate than on base (issue #378 regression gone at 1M edges, 1,000 keys) ✅ pass live e1m summaries: keyed x1000 CPU per write 11297.5 -> 119.5 ms, ack p99 624 -> 4.5 ms; keyed x100 1039.5 -> 127.5 ms; e100 keyed x100 134.7 -> 16.7 ms; perf-gate writes_per_server_cpu_sec PASS at ratio…
The perf gate now covers keyed subscriptions, so the #378 regression cannot recur silently (the gate separates base from candidate on CPU per write) ✅ pass live ev-gate_verdict.json: the delta_keyed fixture produces a PASS/FAIL verdict on writes_per_server_cpu_sec (12 vs 42 writes per CPU second, the base arm regressed)
Keyed delta latency stays bounded on the candidate, and sharing does not make deltas wait more than about twice as long as the views evaluated in parallel ✅ pass live ev-gate_report.md: delta p50 10.6 ms, p99 16.6 ms (bounded; the higher idle delta is the trade the user accepted); e1m keyed x1000 delta p99 80.4 ms vs 1103.9 ms on base; the candidate server log has…
  • Read-only inspection of the user-recorded locked benchmark job on sam-dev-benchmarks (~/bench/fix-keyed-regress/results/{ev-gate,e1m,e100}), confirming it ran exactly candidate 1b215441 against baseline 67a9782f
  • perf-gate-1b215441 run --fixtures delta_keyed --rounds 6 --server-cpus 8-31 (ev-gate report.md / verdict.json / summary.md / bench.txt): 300 keyed agents, 12 runs, exit 0
  • Views benchmark at 1M edges, keyed x1/x10/x100/x1000, base vs candidate (e1m summaries) plus a count of subscription_family_stops_sharing in each server log
  • Views benchmark at 100k edges, keyed x100, base vs candidate (e100 summaries)
  • cargo test --lib subscription::parameterized (29 tests, including the new latency-ceiling test a_round_saving_work_shares_while_at_most_twice_as_slow_as_the_views_in_parallel)
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

jsam added 4 commits October 5, 2026 20:41
…e work, and judge again as views join (#378)

A family of keyed subscriptions (one bound view per session, `?r1(H_k, Y)`)
shared one evaluation per write only while a round was no slower than the
views' own evaluations run in parallel on the compute permits. That compares
latency on an idle server and ignores the work: with 18 permits a family
accepted up to 18 times the CPU for equal latency, and every own evaluation
holds a permit that writes and reads wait for.

#304 made bound rule reads about five times cheaper (`?r1(400,Y)` at 100k
edges: 6.3 to 1.2 ms). Own evaluations then looked faster in parallel than a
round, so keyed families stopped sharing (logged on main at 1M edges:
`shared_us=85445 own_us=9739 bindings=100 permits=18`), and the backoff after
that verdict outlasted the 1,000 views that joined later. On the views
benchmark a write with 100 keys at 100k edges cost 154 ms of server CPU
instead of 46, and with 1,000 keys at 1M edges 11.9 s and a 643 ms ack
instead of 0.18 s and 3.8 ms.

- A round now also keeps sharing when it does at most half the views' own
  evaluations' combined work.
- A family that stopped sharing probes again as soon as it has twice the
  bindings it had when it stopped, instead of waiting out a backoff that
  grows with the bindings: a verdict reached while the first views
  subscribed no longer holds for the many that follow.

On the benchmark host (servers on 24 CPUs, 18 compute permits) the issue's
case, 1M edges with keyed 1, 10, 100 then 1,000 subscribers, now costs
117 ms of server CPU per write at 1,000 keys, with a 4.0 / 4.3 ms ack
p50/p99 and a 75 / 79 ms delta p50/p99 (main: 11,812 ms, 649 / 687 ms,
689 / 1,212 ms; before #304: 180 ms, 3.8 / 8.3 ms, 75 / 104 ms). At 100 keys
on 100k edges: 17 ms per write (main 154, before #304 46).
… CPU per write (#378)

`delta_keyed`: 300 agents, each subscribed to its own key `?r1(H_k, Y)` of a
deployed rule over 100K edges; an open-loop writer adds one row to one key
every 20 ms. Every write refreshes all 300 views, which differ only in their
constant, so the engine must evaluate the family once per write rather than
each view's own query. Besides delta and ack latency, the fixture reports
`writes_per_server_cpu_sec`, writes per second of server CPU over the write
phase, which shows lost sharing even on a host idle enough for the deltas
to arrive in time. Its delta p50/p99, ack p99 and CPU rate join the
policy's required set, and the fixture joins the gate's default fixtures.

Six rounds on the benchmark host. Against the commit before #304
(6ac5322), every required metric passes: delta p50 10.5 ms on both, delta
p99 29.7 to 16.6 ms, ack p99 20.3 to 9.6 ms, 2.3 times less server CPU per
write. Against current main the fixture shows the trade the sharing fix
makes, which is accepted: 6 to 8 times less server CPU per write and a
better tail under load (at a write every 10 ms main's delta p99 reaches
51 ms, the fix's stays under 19 ms), for a higher idle delta p50 (5.8 to
10.2 ms), because main evaluates all 300 views in parallel at that CPU cost.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant