Add opt-in slice presize (//lightning:presize directive + ,presize tag)#7
Open
JohanLindvall wants to merge 4 commits into
Open
Add opt-in slice presize (//lightning:presize directive + ,presize tag)#7JohanLindvall wants to merge 4 commits into
JohanLindvall wants to merge 4 commits into
Conversation
Presize a slice whose struct element holds only flat scalars and one-dimensional leaf collections (scalars/strings/any) to its counted length, replacing append-doubling reallocations with a single make. This is off by default and opt-in via either a //lightning:presize type directive (whole root) or a ,presize json-tag option (per field, propagating through slices/maps/pointers and stopping at struct boundaries, like nocopy/lax). structSkipIsCheap gains a relaxed arg (gated by isLeafType) that admits leaf-collection structs while still rejecting collection-of-collection and collection-of-struct, so the multi-dimensional coordinate arrays slicePresize deliberately skips are never presized regardless of the directive. The presize flag threads through field/valueDecoder/sliceDecoder/arrayDecoder/mapDecoder with a Presize suffix/memo-key bit so tagged and untagged slices of the same type get distinct decoders. Measured (citm areas tagged): allocs -54%, B/op -46%, time +5.6..7.6% — the count scan over tiny elements costs more wall-time than the reallocs it saves, hence opt-in for callers that value the allocation cut (e.g. GC pressure in a long-running service). marine_ik bones is the case where it wins on time too (-3.8%, -31% B/op); the split is array/element-size dependent and not statically decidable. Covered by conformance TestPresizeDirective and TestPresizeTag. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Tag the seatCategories[].areas field with ,presize. Its element is a struct of a scalar (areaId) plus a 1-D leaf collection (blockIds []any, always empty in the corpus), so presizing it to the counted length replaces the append-doubling reallocations (decodeAreas was ~19% of the decode in growslice) with a single make: allocs -54%, B/op -46%, at +5.6..7.6% decode time. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
bench/citm_catalog: presize the areas slice
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds an opt-in presize for slices of leaf-collection structs: preallocate a slice to its counted element length (one
make) instead of letting it grow byappend-doubling. Enabled two ways://lightning:presize— type directive, applies to every eligible slice the root reaches.,presize— json-tag option, per-field; propagates through slices/maps/pointers and stops at struct boundaries, exactly likenocopy/lax.Why off by default
It's a space-for-time trade. Measured with
,presizeon citm'sareasfield:The
CountArrayElementsscan doubles the per-element walk, which costs more wall-time than the reallocations it saves on tiny (~30-byte) elements — so on the time-focused microbenchmarks it's a small loss. It's a win on time too when arrays are large (marine_ikbones[].pos: −3.8% time, −31% B/op). The split is array/element-size dependent and not statically decidable, so it's an explicit opt-in rather than a cost heuristic — aimed at long-running services that care about GC pressure.Safety
structSkipIsCheapgains arelaxedarg (gated byisLeafType) that admits structs whose only non-flat fields are 1-D collections of scalars/strings/any(citmareas[].blockIdsis a[]anythat's always[]). It still rejects collection-of-collection and collection-of-struct, so the multi-dimensional coordinate arraysslicePresizedeliberately skips (the documented +155% disaster on canada/large-json) are never presized regardless of the directive. The flag threads throughfield/valueDecoder/sliceDecoder/arrayDecoder/mapDecoderwith aPresizesuffix/memo-key bit so tagged and untagged slices of the same type get distinct decoders.Tests
TestPresizeDirective— directive presizes leaf-collection slices, leaves multi-dim arrays correct, handles empty/non-empty/null.TestPresizeTag— tagged vs untagged slices decode identically.CLAUDE.md updated (directive list,
slicePresizeopt-in entry with numbers + rationale, cross-ref from the "tried and rejected" entry).🤖 Generated with Claude Code