Record basic validation allocation savings

This commit is contained in:
2026-10-09 00:15:06 +00:00
parent ed7c27324d
commit dd89be3b03

View File

@@ -2,7 +2,7 @@
Implement the remaining local work in the [performance roadmap](performance.md) Implement the remaining local work in the [performance roadmap](performance.md)
in order. Each sequential stage is scoped for one Luna coding-agent prompt. in order. Each sequential stage is scoped for one Luna coding-agent prompt.
Stage 1 is complete; Stages 2–14 remain pending. Update status and evidence Stages 1–2 are complete; Stages 3–14 remain pending. Update status and evidence
as each work unit lands. as each work unit lands.
The completed inspection plan is preserved at The completed inspection plan is preserved at
`481e2d4:docs/roadmap/implementation.md` in Git history. `481e2d4:docs/roadmap/implementation.md` in Git history.
@@ -127,6 +127,11 @@ calls, allocation assertions, or source parsing hidden in the compiled path.
## Stage 2 — Check Basic Output Emptiness Without A String Copy ## Stage 2 — Check Basic Output Emptiness Without A String Copy
**Status: Complete (2026-10-09).** Basic validation now checks the response
bytes directly. Behavioral coverage includes empty bytes, ASCII and Unicode
whitespace, ordinary text, and arbitrary non-UTF-8 bytes. The comparison with
the Stage 1 benchmark fixture is recorded below.
**Outcome:** Basic validation avoids a response-sized temporary string. **Outcome:** Basic validation avoids a response-sized temporary string.
**Work:** **Work:**
@@ -576,6 +581,48 @@ conditional decisions, and final verification in this section as the remaining
stages complete. Keep the feature roadmap focused on target state and progress stages complete. Keep the feature roadmap focused on target state and progress
rather than duplicating the staged procedure. rather than duplicating the staged procedure.
### Basic-Validation Copy Comparison
The before measurement uses the unchanged Stage 1 benchmark fixture at commit
`05fe13d` (`Record validation and rendering baselines`), immediately before the
production change. The after measurement uses the same fixture and benchmark
implementation at `ed7c273` (`Avoid copying output during basic validation`).
Environment and module versions match the baseline above: Linux/amd64, Intel
Core i5-7260U @ 2.20 GHz, parallelism 4, Go 1.26.8, ConfigKit `v0.5.0`, JSON
Schema `v6.0.2`, and backend modules `v3.20260930.0`.
Command for both revisions (five 500 ms samples, without the race detector):
```sh
GOTOOLCHAIN=local GOWORK=off GOPROXY=off GONOPROXY=none GOSUMDB=off \
go test -mod=readonly -run '^$' -bench '^BenchmarkBasicValidation$' \
-benchmem -benchtime=500ms -count=5 ./internal/validate
```
Times list all five `ns/op` samples in command order, followed by median and
range. Allocation figures are `B/op; allocs/op`.
| Benchmark case | Before `ns/op` (median; range) | Before allocations | After `ns/op` (median; range) | After allocations |
| --- | --- | --- | --- | --- |
| Short text | 45.39, 45.10, 42.20, 44.19, 44.21 (44.21; 42.20–45.39) | 0; 0 | 41.80, 41.19, 39.90, 41.02, 39.18 (41.02; 39.18–41.80) | 0; 0 |
| 1 MiB nonempty text | 216006, 220902, 226243, 228846, 184748 (220902; 184748–228846) | 1048576–1048577; 1 | 39.76, 42.16, 41.61, 40.79, 40.92 (40.92; 39.76–42.16) | 0; 0 |
| ~1 MiB whitespace-only text | 766108, 709398, 731226, 915411, 787797 (766108; 709398–915411) | 1048592–1048594; 2 | 558919, 562202, 561004, 555487, 564593 (561004; 555487–564593) | 16; 1 |
| Unicode whitespace | 126.6, 113.2, 116.7, 111.6, 115.2 (115.2; 111.6–126.6) | 16; 1 | 115.1, 116.9, 106.1, 111.2, 110.9 (111.2; 106.1–116.9) | 16; 1 |
The 1 MiB nonempty case's median fell from 220902 ns/op to 40.92 ns/op while
response-sized allocation fell from 1048576–1048577 bytes to zero. The
whitespace case still scans the body and returns a small validation failure;
its response-sized temporary string is gone, reducing allocation from about
1 MiB and two allocations to 16 bytes and one allocation. Small-input timings
and the Unicode case remain in the same order of magnitude. The benchmark no
longer reports bytes per second because the nonempty fast path can classify a
body from its boundary bytes without scanning the full body; latency and
allocation comparisons remain meaningful.
Focused verification passed on the implementation commit:
`go test -mod=readonly ./internal/validate ./internal/usecase`. The benchmark
family above was rerun on that commit with the recorded command.
## Open Questions ## Open Questions
No consumer-policy decisions remain open. File reservation and encoding error No consumer-policy decisions remain open. File reservation and encoding error