Repository navigation
runtime: optimize slice and string map paths - #3032
Conversation
There was a problem hiding this comment.
Review: runtime string-map and slice fast paths
Overall this is a clean, well-reasoned optimization. I verified the two hot-path changes against their surrounding code and the helpers they replace, and ran each dimension (correctness/safety, performance, code quality, docs) over the diff.
What the PR does
map_faststr.go: replacesstringStructOf(&ky)with a stack-localstringStruct{unsafe.StringData(ky), len(ky)}and addshashMapKeyString, which keeps the temporary string header on the stack viac.Allocabefore callingt.Hasher— a faithful mirror of the existinghashMapKey32/hashMapKey64helpers. This removes the per-operation header heap allocation.z_slice.go:NewSlice2/NewSlice3Boundsfold the signed/negative/unsigned index checks into singleuint64(idx) > uint64(bound)comparisons and move theboundsSliceAcap/boundsSliceAlenselection onto the cold panic path.
Correctness & safety — verified sound
- The
uint64rewrite is semantically equivalent to the removedboundsOutOfRange/boundsAbove, givencapis non-negative (confirmed at the call sites inssa/datastruct.go:nCapcomes fromSliceCap/arrayLen/StringLen, all ≥ 0). Negative signed and high-bit unsigned indexes still panic; valid0 ≤ i ≤ j ≤ capstill pass. unsafe.StringDataon an empty key is safe here: thek.len != key.lenguard plusmemequal'ssize == 0short-circuit prevent any zero-size deref, and the 4-byte long-key comparisons run only underkey.len >= 32.- GC-safety is preserved: the
Allocastack header stays live across thet.Hashercall, and the key stored into the bucket roots the same backing bytes (covered byTestMapFastStringKeysSurviveGrowthAndGC). boundsOutOfRange/boundsAboveare correctly retained forz_string.go.
The two inline notes below are minor maintainability suggestions — nothing blocking.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
LLGo WebAssembly build benchmarks
WebAssembly output sizes
LLGo WebAssembly build measurements
Compared with |
LLGo baseline benchmarks
String equality benchmarks
Program measurements
Core language and compiler benchmarks
Timer runtime benchmarks
Compared with |
cpunion
left a comment
There was a problem hiding this comment.
Reviewed 2e2783d. I found no blocking correctness issues.
The string header is borrowed synchronously by the hasher; the empty-key and stored-key paths retain their existing semantics. The slice checks preserve the upper-to-lower ordering: after checking against nonnegative cap, each subsequent bound is known to fit int before conversion. Signedness is still retained for panic formatting, including negative signed and high-bit unsigned indices.
Validation performed with a compiler built from this head:
- Native macOS/arm64: the four new string-map tests at O0/O2, plus the existing map and slice-bounds/panic-text regressions.
- Emscripten32 and Memory64: the same four new string-map tests, copied unchanged into a temporary pure-Go test package to avoid the original package's platform-specific C declarations; Emscripten32 also passed the existing map and bounds regressions.
- Extracted old/new slice checks: 279,000 boundary combinations produced identical results and panic arguments, covering signedness flags and 32/64-bit boundary values. This comparison is not a claim of native 32-bit CPU execution.
One non-blocking comment below clarifies the allocation benefit's platform scope.
No description provided.