barcodes: signed matrix words keep the encoder on one JIT specialization - #315
Merged
Merged
Conversation
Encode timings depended on which symbol size a process saw first. A version 1 symbol fits one 32-bit word per row and never fills a word, so a JIT meeting it first specializes the encoder on small integers; the first larger symbol produces full words, which read as doubles from a Uint32Array, and the recompiled mixed-type code runs about 1.4x slower for the rest of the process (raw v8: 17 µs warmed on its own size, 25 µs warmed on v1; the reference implementation flips the same way). The matrix is now an Int32Array. Every word use is bitwise or a popcount, both sign-agnostic, so the `>>> 0` coercions and the unsigned mask literals go: masks are `~(-1 << bits)` and `-1`. A full word is an ordinary int32 in every version and the encoder keeps one specialization whatever order sizes arrive in. Encoder oracle byte-identical on 1452 checks; decoder oracle identical on 192. Measured, v1-then-v8 pattern, five processes: 16.5 16.4 16.5 16.7 16.6 µs (was 24.8 25.0 25.4 25.3 24.7). Warmed on its own size: unchanged. README gains a Performance section with the encode and decode tables against paulmillr/qr 0.7.0 (best of three processes, standard sequence, Bun 1.4.0, Apple M5) and the explanation above.
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.
Summary
Encode timings depended on which symbol size a process saw first. A version 1 symbol never fills a 32-bit word, so a JIT that meets it first specializes the encoder on small integers; the first larger symbol produces full words, which read as doubles from a
Uint32Array, and the recompiled mixed-type code runs ~1.4x slower for the rest of the process. The reference implementation flips the same way.The matrix is now an
Int32Array. Every word use is bitwise or a popcount, both sign-agnostic, so the>>> 0coercions and unsigned mask literals go. A full word is an ordinary int32 in every version and the encoder keeps one specialization whatever order sizes arrive in.The README gains a Performance section with the encode and decode tables against paulmillr/qr 0.7.0 and this explanation.
Measurements
v1-then-v8 pattern, raw v8 encode, five processes (µs):
Warmed on its own size: unchanged (16–17 µs both). Decode rows unchanged.
Verification
bun run test:all26 lanes, 9895 tests