Skip to content

perf(decoder): mirror the destuff-once positional MagSgn reader to NEON and WASM#458

Merged
osamu620 merged 1 commit into
mainfrom
perf/decode-posreader-isa-mirror
Jul 2, 2026
Merged

perf(decoder): mirror the destuff-once positional MagSgn reader to NEON and WASM#458
osamu620 merged 1 commit into
mainfrom
perf/decode-posreader-isa-mirror

Conversation

@osamu620

@osamu620 osamu620 commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Continuation of #457, which was auto-closed when its stacked base branch (#456's perf/decode-step2-posreader) was deleted after merging. Same branch, now rebased onto main (single commit on top of the merged #456).

What

Applies the same MagSgn reader redesign as #456 to the NEON and WASM-SIMD fwd_buf classes: destuff the whole segment once in the constructor (per-thread scratch), fetch at absolute bit positions with no serial reader state, and reduce advance() to an integer add with the same ≥128-bit fail-fast range check.

The destuff pass is a new shared portable scalar implementation (destuff_fwd_portable): 16 source bytes per iteration in the common no-0xFF case (branch-free has-value bit trick on two 64-bit words), per-byte bit accumulator only for chunks containing 0xFF. The x86 class keeps its SSE variant of the same algorithm.

ISA-specific care:

  • WASM shift counts are taken modulo 64, so the fetch carry lanes are masked out when (pos & 7) == 0.
  • NEON USHL yields 0 for out-of-range shift counts, so no special case is needed.
  • The scalar fwd_buf is deliberately untouched: its reader is already a single Creg >>= n per advance, so a destuff pass would only add cost — the same structural reason the earlier VLC destuff experiment regressed.

Results

WASM-SIMD, Node 24 on Zen 5, single-thread, min-of-15 in-process iterations, same-moment A/B, 3840×2160 fixtures:

fixture before after delta
8-bit lossless 105.9 ms 98.6 ms −6.9%
8-bit lossy 153.3 ms 135.4 ms −11.7%

NEON has the identical reader structure and is expected to behave the same, but was not perf-measured here (no ARM hardware available); the ARM CI runners validate correctness, and an Apple-silicon measurement is a follow-up.

Correctness

  • Decoded output through the new WASM-SIMD build is pixel-byte-identical to the native reference on all four fixtures (8/16-bit lossless, lossy, 512×8 streaming blocks).
  • Native suite: 463/463 pass (including the node-based WASM conformance tests, which run the new SIMD build).
  • Fail-fast on malformed input preserved on both ISAs (same check + exception as the x86 reader).
  • A manually dispatched full CI matrix on this branch (pre-rebase, identical content) passed all 9 platforms: https://github.com/osamu620/OpenHTJ2K/actions/runs/28568854539

🤖 Generated with Claude Code

https://claude.ai/code/session_01M9cKpzqghsLxJUu7kkyRAw

…ON and WASM

Apply the same reader redesign as the AVX2 commit to the NEON and
WASM-SIMD fwd_buf classes: the constructor destuffs the whole MagSgn
segment once into a per-thread scratch buffer, fetch()/fetch_raw()
return the 128 bits at an absolute bit position (two staggered 8-byte
loads shifted into alignment), and advance() becomes an integer add
with the same >=128-bit fail-fast range check.

The destuff pass itself is a new shared portable scalar implementation
(destuff_fwd_portable): 16 source bytes per iteration in the common
no-0xFF case, detected with the branch-free has-value bit trick on two
64-bit words, falling back to a per-byte bit accumulator only for
chunks that contain 0xFF. The x86 class keeps its SSE variant of the
same algorithm.

ISA notes: WASM shift counts are modulo 64, so the fetch carry lanes
are masked when (pos & 7) == 0; NEON USHL yields 0 for out-of-range
counts, so no special case is needed there.

WASM-SIMD (Zen 5 host, Node 24, single-thread, min-of-15 in-process,
same-moment A/B, 3840x2160 fixtures):
  8-bit lossless  105.9 ms -> 98.6 ms   (-6.9%)
  8-bit lossy     153.3 ms -> 135.4 ms  (-11.7%)
NEON is expected to behave like the other two ISAs (identical reader
structure) but was not perf-measured here (no ARM hardware); CI's ARM
runners validate correctness.

Decoded output is pixel-byte-identical to the native reference on all
four fixtures through the new WASM-SIMD build, and the native suite
passes 463/463. The scalar fwd_buf is deliberately left unchanged: its
reader is already a single Creg shift per advance, so a destuff pass
would only add cost (the Lever-1 lesson).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M9cKpzqghsLxJUu7kkyRAw
@osamu620 osamu620 merged commit 136482e into main Jul 2, 2026
9 checks passed
@osamu620 osamu620 deleted the perf/decode-posreader-isa-mirror branch July 2, 2026 06:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant