perf(encode): emit in place, pool the buffer and cache interface flags
Test / test (push) Successful in 1m29s

This commit is contained in:
2026-09-20 22:15:38 +02:00
parent 3a4bd74bf0
commit 582222738b
4 changed files with 337 additions and 118 deletions
+16 -8
View File
@@ -102,15 +102,23 @@ sequenceDiagram
setter methods are not, and must finish before the value is shared.
- The parser is allocated per `ParseContext` call; the parser itself caches
nothing between documents.
- The one piece of shared state is the struct-schema cache in `decode.go`: a
`sync.Map` keyed by `reflect.Type`, holding the flattened field layout the
decoder and the encoder both consult. A schema is immutable once published,
so concurrent callers only race to build an identical value, the same
trade-off `encoding/json`'s field cache makes. The cache grows with the
number of distinct struct types, never with document size.
- The shared state is a set of caches and pools whose entries are immutable
once published, each growing with the number of distinct types rather than
with document size: the struct-schema cache in `decode.go` (a `sync.Map`
keyed on `reflect.Type`, holding the flattened field layout the decoder and
the encoder both consult), the per-type interface flag caches in `decode.go`
and `encode.go` (recording where `Marshaler`, `Unmarshaler` and the text
interfaces can be found, so a walk builds an interface value only where the
assertion can succeed), each fronted by a monomorphic hint holding the type
resolved last, and the encoder's output-buffer pool in `encode.go`
(`sync.Pool`, buffers returned to it only within a 1 MiB retention cap). A
published schema or flag set never mutates, so concurrent callers only race
to build an identical value, the same trade-off `encoding/json`'s field
cache makes.
- The date-time wrappers are values, not pointers, and are immutable in use.
- Nothing in the library starts goroutines; apart from the schema cache above,
which never mutates a published entry, there is no shared mutable state.
- Nothing in the library starts goroutines; apart from the caches and the pool
above, which never mutate a published entry, there is no shared mutable
state.
## Dependencies