Repository navigation
v1.9.0 remove per-call allocations from encode/decode hot paths - #22
Merged
Merged
Conversation
- Reuse a per-format BufferWriter in encodeInto() and add encodeIntoLength(). - Reuse a per-format BufferReader in decode()/decodeInto(), with a re-entrancy guard. - Copy Buffer fields with Uint8Array.set() instead of creating a view. - Read peekHeader() without a DataView for Uint8Array and DataView input. - Reuse decoded arrays when their length changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The writer and reader now keep a DataView over the whole buffer and track a base offset and length, so retargeting to another view of the same buffer (slot pools, subarrays of one packet) no longer allocates. Reads and writes are bounds-checked against the target view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
reececomo
commented
Nov 8, 2026
reececomo
left a comment
Owner
Author
There was a problem hiding this comment.
✅ LGTM — Clean allocation-free retargeting with solid bounds checks, re-entrancy fallback and thorough tests - Couple of minor nits
reececomo
commented
Nov 8, 2026
Address review: a nested call finds no shared reader or writer and creates its own, and the outer call restores its instance when it finishes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Removes per-call heap allocations from encode, decode and
peekHeaderso that hot-path encode/decode in real-time loops produces less garbage.Changes
encodeInto()reuses oneBufferWriterper format viaBufferWriter.$reset(). A newencodeIntoLength(data, bytes): numberreturns the byte count without creating a view. A target that is too small still throwsTinybufError.decode()anddecodeInto()reuse oneBufferReaderper format viaBufferReader.$reset(). The shared reader is taken out of the format while it is in use, so a decode inside another decode, such as from a field transform, creates its own reader. Encode works the same way.BufferWriter.$writeBytes()copies withUint8Array.set()and only wraps non-Uint8Arrayinput.peekHeader()readsUint8ArrayandDataViewinput without allocating, and now throwsRangeErrorwhenever the input itself has fewer than 2 bytes.For 1 and 2, the writer and reader keep a
DataViewover the whole underlyingArrayBufferand track a base offset and length. Retargeting to another view of the same buffer, such as slots in a pool or subarrays of one packet, reuses theDataView. Reads and writes are bounds-checked against the target view. ADataViewpassed todecode()is adopted directly.New tests in
src/__tests__/allocations.test.tscover shared-buffer slots, subarray decoding, view bounds, re-entrancy, error recovery, array reuse, and constructor counts for the zero-allocation paths. The shared reader and writer keep a reference to the last buffer until the next call.Also adds
.github/workflows/publish.yml, copied from the pixijs-* repos. It publishes to npm with provenance through OIDC and creates a GitHub release whenever thepackage.jsonversion changes onmain.🤖 Generated with Claude Code