Repository navigation
perf: reduce per-value overhead in encode/dispatch and centralize string writing - #120
Merged
Merged
Conversation
Write the length prefix and UTF-8 payload with one _ensure per string in Writer.writeString, instead of separate header/payload reservations that each re-checked buffer growth. Also dispatch encodeValue on typeof for the primitive types (string/number/boolean) before strict-equality probes, which avoids several wasted comparisons for the most common values. Byte-exact for fixstr/str8/str16/str32 boundaries and surrogate pairs; suite passes on Node 22/24/26.
Decode null/false/true directly in tryDecode instead of delegating to a decodeConstants function (one less call per constant). Hoist '__proto__' to a module-scope constant so building plain objects doesn't re-create a local binding per map. Suite passes on Node 22/24/26.
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.
A profiling-driven cleanup of the remaining per-value overhead in the encoder and constant dispatch.
Changes
Encoder
Writer.writeString. The length prefix and UTF-8 payload are written with a single buffer reservation per string, so the header and payload no longer each trigger a separate buffer-growth check. The four header forms (fixstr / str8 / str16 / str32) are handled in one place.encodeStringreduces to computing the byte length and calling it.encodeValueontypeoffirst. For the most common values (strings, numbers, booleans), this replaces several strict-equality probes with a singletypeofcheck.nullis still handled explicitly (it istypeof 'object'), so behavior is unchanged.Decoder
tryDecode, removing adecodeConstantscall per constant.__proto__constant to module scope, so building plain objects no longer re-creates the local binding for every map.Validation
standardlint clean.Note on impact
These are reductions in per-value JS overhead; they do not change the wire format. Re-profiling shows encode/decode are dominated by inherent native UTF-8 work (
utf8Slice/utf8Write), so measurements on msgpackr's string-heavy benchmark are within the machine's noise. The changes are correct and byte-exact, and simplify the hot paths.