Skip to content

Commit c260f03

Browse files
pegeaetherclaude
andcommitted
docs: refresh the benchmark baseline for the :string fast path; mark v0.5 item 9 done
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPAgXWnvgpKcUw71GHStXC
1 parent 43f3c9c commit c260f03

2 files changed

Lines changed: 38 additions & 26 deletions

File tree

ROADMAP.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,13 @@ docs/design/v05-plan.md (three-proposal panel, two verifying judges).
5353
generated code, `make check-versions` (fails on a skewed site),
5454
docs/releasing.md, and `SBCL / Linux aarch64 (best-effort)` — green on
5555
its first run.
56-
9. **`:string` ASCII fast path** — a typed ASCII loop before babel (both
57-
judges measured ~2.5×); zero-copy `:string` stays refused.
56+
9.**`:string` ASCII fast path** — a typed check-and-store loop in
57+
both directions, babel from the first char/byte ≥ 128, a peek before
58+
any allocation so non-ASCII text pays nothing extra: 64 KiB ASCII
59+
1015 → 318 µs (3.2×), non-ASCII unchanged. Differentially tested
60+
against babel on all three hosts (no counterexample in ~12k checks)
61+
and swept adversarially through echo; zero-copy `:string` stays
62+
refused.
5863
10. **Miri over the generated shims** — optional; cut first.
5964
11. **User-facing docs claim audit, last** — README still says
6065
"Scope (v0.1)"; every capability claim gets a citation or is deleted.

docs/benchmarks.md

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ compilation policy; nothing is tuned. Numbers vary by machine and are
1515
nanoseconds, byte and vector transfers scaling linearly at memcpy speed,
1616
a borrowed callback a small multiple of a call.
1717

18-
## Baseline — 2026-09-02, commit 5241783
18+
## Baseline — 2026-09-03, commit 43f3c9c
1919

2020
| | |
2121
|---|---|
@@ -27,27 +27,28 @@ a borrowed callback a small multiple of a call.
2727
Raw output of `make bench`:
2828

2929
```
30-
scalar call (add i64 i64) 20.0 ns/call
30+
scalar call (add i64 i64) 25.0 ns/call
3131
scalar call, no args 25.0 ns/call
32-
handle method (gate + call) 240.0 ns/call
32+
handle method (gate + call) 275.0 ns/call
3333
handle create + free 650.0 ns/call
34-
string round trip (8 B ASCII) 950.0 ns/call
35-
string round trip (1024 B ASCII) 22701.5 ns/call
36-
string round trip (65536 B ASCII) 1015066.3 ns/call
37-
string round trip (1 KiB non-ASCII) 39452.6 ns/call
34+
string round trip (8 B ASCII) 600.0 ns/call
35+
string round trip (1024 B ASCII) 11100.7 ns/call
36+
string round trip (65536 B ASCII) 317620.7 ns/call
37+
string round trip (1 KiB non-ASCII) 38802.6 ns/call
38+
rx count over 1 MiB (&str in, 1 match) 2305160.0 ns/call
3839
bytes in (sum, 8 B) 200.0 ns/call
3940
bytes round trip (rev, 8 B) 500.1 ns/call
40-
bytes in (sum, 1024 B) 500.1 ns/call
41-
bytes round trip (rev, 1024 B) 1200.0 ns/call
42-
bytes in (sum, 65536 B) 21251.3 ns/call
43-
bytes round trip (rev, 65536 B) 39952.6 ns/call
44-
bytes in (sum, 1048576 B) 323521.0 ns/call
45-
bytes round trip (rev, 1048576 B) 731048.0 ns/call
46-
vec i64 round trip (8 elts) 650.0 ns/call
47-
vec i64 round trip (1024 elts) 6600.4 ns/call
48-
vec i64 round trip (65536 elts) 192512.5 ns/call
49-
borrowed callback (100 invocations) 48003.0 ns/call
50-
stored callback (same thread) 180.0 ns/call
41+
bytes in (sum, 1024 B) 550.0 ns/call
42+
bytes round trip (rev, 1024 B) 1100.0 ns/call
43+
bytes in (sum, 65536 B) 22451.4 ns/call
44+
bytes round trip (rev, 65536 B) 44102.9 ns/call
45+
bytes in (sum, 1048576 B) 319521.5 ns/call
46+
bytes round trip (rev, 1048576 B) 702045.0 ns/call
47+
vec i64 round trip (8 elts) 600.0 ns/call
48+
vec i64 round trip (1024 elts) 10550.7 ns/call
49+
vec i64 round trip (65536 elts) 191012.5 ns/call
50+
borrowed callback (100 invocations) 39002.5 ns/call
51+
stored callback (same thread) 170.0 ns/call
5152
```
5253

5354
## Reading it
@@ -68,12 +69,18 @@ stored callback (same thread) 180.0 ns/call
6869
(0.32 ms and 0.19 ms) with the element-wise marshaller they replaced
6970
(7.67 ms and 57.3 ms, measured the same way on this host before the
7071
change — see the v0.3 groundwork commit).
71-
- **Strings are the slow path**, and deliberately so for now: a
72-
`:string` round trip goes through UTF-8 encode/decode on the Lisp
73-
side, so 64 KiB costs ~1 ms where the same bytes as `:bytes` cost 40 µs.
74-
Zero-copy `:string` is refused-with-cause in the v0.3 plan (bodies are
75-
octets; no demand case); pass large payloads as `:bytes` and decode
76-
what you need.
72+
- **Strings: ASCII takes a typed loop, the rest goes through babel.**
73+
A `:string` crosses as UTF-8 with a copy in each direction (BOUNDARY
74+
§4; zero-copy `:string` is refused-with-cause in the v0.3 plan). Since
75+
v0.5 the loader checks-and-stores ASCII text in a typed loop and hands
76+
the bytes to babel at the first char/byte ≥ 128, so a 64 KiB ASCII
77+
round trip costs ~0.32 ms where the 2026-09-02 baseline (in git
78+
history) measured ~1 ms; the same bytes as `:bytes` cost 40 µs, so
79+
octet payloads still belong in `:bytes`. Non-ASCII text costs what it
80+
did (the 1 KiB row). The rx row is a real `&str` consumer: 1 MiB into
81+
`regex-count` with the digits placed once at the end, so the regex side
82+
is a memchr sweep and the row is the boundary — ~2.3 ms, in line with
83+
16× the 64 KiB row.
7784
- **Callbacks**: a borrowed callback invocation is ~480 ns (100 per
7885
export call); a stored callback from the same thread is ~180 ns. The
7986
cross-thread stored path adds foreign-thread adoption, not measured

0 commit comments

Comments
 (0)