You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Closes the bracket scenarios 3 + 5 left loose: per-iteration cost is
(handshake + N * request) / N which approximates the per-request cost
the Phase E rollout sees once the handshake is amortised across a
kept-alive pool.
Adds:
- bench/gateway_latency.exs: scenario 6
"mTLS amortised (test CA, N requests over kept-alive)" plus a
dedicated kept-alive acceptor on port 19_879 running an echo loop
(separate listener from scenario 5 so its close-on-handshake shape
doesn't kill the kept-alive connection). N=16; payload is a tiny
8-byte ASCII frame.
- bench/baseline.json: new scenario key with TODO placeholders;
_schema_version bumped to 0.3.0-scaffold.
- docs/perf-contract.md: scenarios table + targets table now list six
scenarios; the previously deferred amortised follow-up is moved
out of "Out of scope" into in-scope.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: bench/baseline.json
+10-3Lines changed: 10 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
{
2
-
"_comment": "Phase D scaffold-placeholder baseline (standards#99). Numbers are TODO. Phase D-1 (PR #12) wired the Benchee harness + this file + the CI gate; Phase D-2 (PR #14) added a real in-process loopback backend so the 'exact route allow (proxy 200)' scenario measures real dial-and-read cost instead of port-1 connection-refused; Phase D-3 (this update) added two scenarios -- 'trust-header rewrite (Proxy.build_backend_headers)' isolating the Phase A contract-header construction cost, and 'mTLS handshake (test CA)' isolating per-handshake cost using the Phase B real-CA fixture. Phase D-4 collects real numbers via the `perf: rebaseline` ritual in docs/perf-contract.md and flips `_status` to 'active' to arm the CI gate. DO NOT trust these numbers; the perf-regression CI gate is intentionally non-blocking until that flip.",
3
-
"_schema_version": "0.2.0-scaffold",
2
+
"_comment": "Phase D scaffold-placeholder baseline (standards#99). Numbers are TODO. Phase D-1 (PR #12) wired the Benchee harness + this file + the CI gate; Phase D-2 (PR #14) added a real in-process loopback backend so the 'exact route allow (proxy 200)' scenario measures real dial-and-read cost instead of port-1 connection-refused; Phase D-3 (PR #22) added two scenarios -- 'trust-header rewrite (Proxy.build_backend_headers)' isolating the Phase A contract-header construction cost, and 'mTLS handshake (test CA)' isolating per-handshake cost using the Phase B real-CA fixture. Phase D-3 follow-up (this update) adds 'mTLS amortised (test CA, N requests over kept-alive)' which holds one connection open and does N=16 send/recv round-trips per iteration, closing the bracket that scenarios 3 + 5 left loose. Phase D-4 collects real numbers via the `perf: rebaseline` ritual in docs/perf-contract.md and flips `_status` to 'active' to arm the CI gate. DO NOT trust these numbers; the perf-regression CI gate is intentionally non-blocking until that flip.",
3
+
"_schema_version": "0.3.0-scaffold",
4
4
"_generated_at": "TODO(Phase D-4): replace with ISO8601 timestamp from collection run",
"mTLS amortised (test CA, N requests over kept-alive)": {
41
+
"_comment_d3": "Phase D-3 follow-up scenario. One :ssl.connect/4 followed by N=16 send/recv round-trips on the open connection, then :ssl.close/1. Per-iteration cost is (handshake + N * request) / N, approximating the per-request cost the Phase E rollout sees once the handshake is amortised across a kept-alive pool. Closes the bracket scenarios 3 ('exact route allow (proxy 200)') and 5 ('mTLS handshake (test CA)') left loose. Uses a dedicated kept-alive acceptor on port 19_879 with an echo loop so the connection stays open across the N round-trips; payload is a tiny 8-byte frame so per-request cost is dominated by connection round-trip, not payload write/read.",
42
+
"p50_us": "TODO",
43
+
"p95_us": "TODO",
44
+
"p99_us": "TODO",
45
+
"ips": "TODO"
39
46
}
40
47
},
41
48
"tolerance": {
42
-
"_comment": "Multiplicative regression tolerance applied to each percentile. 1.20 = a PR is allowed to be up to 20% slower than baseline before the gate fails. Phase D-4 will revisit these once we have signal on intra-run variance. D-3 scenarios use the same tolerances pending D-4 calibration; the mTLS handshake scenario is likely the noisiest (TLS RNG draws + cert chain validation timing) and may need a looser p99 cap once we see the spread.",
49
+
"_comment": "Multiplicative regression tolerance applied to each percentile. 1.20 = a PR is allowed to be up to 20% slower than baseline before the gate fails. Phase D-4 will revisit these once we have signal on intra-run variance. D-3 scenarios use the same tolerances pending D-4 calibration; the mTLS handshake scenario is likely the noisiest (TLS RNG draws + cert chain validation timing) and may need a looser p99 cap once we see the spread. The amortised scenario is expected to sit close to N * proxy-200 in per-iteration terms (since the handshake is paid once per 16 round-trips); its variance should be tighter than scenario 5's but looser than scenario 3's.",
Copy file name to clipboardExpand all lines: docs/perf-contract.md
+26-18Lines changed: 26 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,8 +9,10 @@
9
9
> single-lane HCG channel (standards#91) collects the baseline and fills
10
10
> them in. The CI gate is non-blocking until that point. Phase D-3 (this
11
11
> revision) is the last harness-shape change before D-4 collection: it
12
-
> adds the `trust-header rewrite` and `mTLS handshake` scenarios so the
13
-
> baseline attributes those costs independently of the proxy-200 path.
12
+
> adds the `trust-header rewrite`, `mTLS handshake`, and `mTLS amortised`
13
+
> scenarios so the baseline attributes header-rewrite cost, per-handshake
14
+
> cost, and per-request kept-alive cost independently of the proxy-200
15
+
> path.
14
16
15
17
Tracks: `Refs hyperpolymath/standards#99` (Phase D of `standards#91`).
16
18
@@ -24,12 +26,13 @@ backend (added in Phase D-2), since the production gateway always pays
24
26
that cost on an allow path; the loopback strips out real-network RTT and
25
27
real-backend processing time so what remains is the gateway-attributable
26
28
proxy overhead. The `mTLS handshake` scenario (added in Phase D-3)
27
-
covers per-handshake transport cost in isolation. Real production
28
-
backend latency, real-network RTT, and amortised mTLS cost across a
29
-
kept-alive connection remain out of scope — the latter is bracketed by
30
-
the `proxy 200` + `mTLS handshake` scenarios pending D-4 signal.
29
+
covers per-handshake transport cost in isolation, and the
30
+
`mTLS amortised` scenario (added in the Phase D-3 follow-up) covers the
31
+
per-request cost when N=16 requests share one kept-alive TLS connection,
32
+
closing the bracket that `proxy 200` + `mTLS handshake` left loose. Real
33
+
production backend latency and real-network RTT remain out of scope.
31
34
32
-
The five named scenarios match the five Benchee scenarios in
35
+
The six named scenarios match the six Benchee scenarios in
33
36
`bench/gateway_latency.exs`:
34
37
35
38
| Scenario | What it measures |
@@ -39,6 +42,7 @@ The five named scenarios match the five Benchee scenarios in
39
42
|`exact route allow (proxy 200)`| Allow path that proxies to an in-process loopback backend returning 200. Captures the real dial-and-read cost the gateway pays in production. |
40
43
|`trust-header rewrite (Proxy.build_backend_headers)`| Direct call to the `Proxy.__benchmark_build_backend_headers__/1` benchmark seam on a pre-built conn (`assigns[:trust_level] = :authenticated`, `assigns[:request_id]` set). Isolates the Phase A contract-header construction (X-Trust-Level / X-Request-ID / X-Forwarded-*) from policy lookup and network I/O. |
41
44
|`mTLS handshake (test CA)`|`:ssl.connect/4` against a raw `:ssl` acceptor + immediate close. Test CA chain is generated in-memory at bench startup via `:public_key.pkix_test_data/1` — the committed Phase B fixture ships only `*.crt` files (matching `*.key` is gitignored), so the chain is rebuilt with the same `verify_peer` + test-CA shape rather than reusing the on-disk material. Per-handshake cost (cert chain validation + key exchange) in isolation; no HTTP pipeline. Bounds the connection-spike SLO for Phase E rollout. |
45
+
|`mTLS amortised (test CA, N requests over kept-alive)`| One `:ssl.connect/4` followed by N=16 tiny send/recv round-trips on the open connection, then `:ssl.close/1`. Uses a dedicated kept-alive acceptor (separate listener from the handshake-only scenario) with an echo loop, so the connection stays open across the N round-trips. Per-iteration cost is `(handshake + N * request) / N`, which approximates the per-request cost the Phase E rollout sees once the handshake is amortised across a kept-alive pool. Closes the bracket scenarios 3 + 5 left loose. |
42
46
43
47
## Published latency SLOs
44
48
@@ -57,6 +61,7 @@ Reported per scenario, per CI run:
57
61
|`exact route allow (proxy 200)`| TODO | TODO | TODO |
58
62
|`trust-header rewrite (Proxy.build_backend_headers)`| TODO | TODO | TODO |
59
63
|`mTLS handshake (test CA)`| TODO | TODO | TODO |
64
+
|`mTLS amortised (test CA, N requests over kept-alive)`| TODO | TODO | TODO |
0 commit comments