Repository navigation
perf(decode): single-band output renders straight into a zeroed image (system heap win vs zune) - #18
Merged
Merged
Conversation
With one output band (set_single_threaded, or one usable core) the image is allocated zeroed and rows are rendered directly into it, instead of through a row buffer copied into uninitialised capacity. A zeroed allocation of this size comes from fresh, already-zero pages under the Windows heap (and glibc), so the zeroing is free and the per-row copy was pure overhead: it was what still left the default decoder behind zune-jpeg on one core under the system allocator after 0.4.5 (ArtCraft: 1.050x photo, 1.009x frame). Several bands keep the uninitialised path, where a zero-fill would run serially before the bands start. Under a recycling allocator (rusty_alloc) the memset of reused memory costs slightly more than the copy did -- ~2% -- and the decoder still beats zune-jpeg there. One configuration that wins under both allocators, over one tuned to the allocator it was measured with. Byte-identical: 30-file fixture set, and all 30 decoded forwards then backwards in one process (plane reuse across images), single- and multi-threaded, under both allocators: 60/60 identical to 0.4.3. Clippy clean on default / no_std / platform_independent / rayon. Default decode(), pinned to 1 core, ABBA 20x20, wall: system allocator new/0.4.5 (paired) new/zune-jpeg 0.5.15 frame1080 0.927, 20/20 (z -4.47) 0.952, 18/20 (z -3.58) photo2000s 0.932, 20/20 (z -4.47) 0.917, 20/20 (z -4.47) photo2000 0.970, 18/20 (z -3.58) 0.912, 18/20 (z -3.58) rusty_alloc new/0.4.5 (paired) new/zune-jpeg 0.5.15 frame1080 1.021, 1/20 (z +4.02) 0.974, 19/20 (z -4.02) photo2000s 1.010, 6/20 (z +1.79) 0.933, 20/20 (z -4.47) photo2000 1.021, 4/20 (z +2.68) 0.906, 20/20 (z -4.47) 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.
After 0.4.5, ArtCraft still measured the default decoder behind zune-jpeg on one core under the system allocator: 1.050x on the photo and 1.009x on the frame. With a single output band, this PR renders rows directly into a zeroed image, which the Windows heap serves from already-zero pages. That drops the per-row copy into uninitialised memory. Multi-band output keeps the uninitialised path.
One core, default
decode(), vs zune-jpeg 0.5.15:The cost: about 2% vs 0.4.5 under rusty_alloc, where zeroing recycled memory costs a little more than the copy did. It still beats zune there on all three images. Output is byte-identical (60/60 decodes in one process under both allocators). The full table is in the commit message.
🤖 Generated with Claude Code