Skip to content

refactor(simd): replace std::arch and wide with pulp - #11

Open
topi-banana wants to merge 3 commits into
mainfrom
ref/pulp-simd-rewrite
Open

topi-banana wants to merge 3 commits into
mainfrom
ref/pulp-simd-rewrite

Conversation

@topi-banana

Copy link
Copy Markdown
Contributor

Summary

Replaces the simd feature's hand-rolled vector code (std::arch on x86, cfg-selected scalar/NEON/wasm modules, and wide for the CESU-8 scan) with pulp backends, written as WithSimd implementations and dispatched at run time with Arch::dispatch.

Changes

  • nanonbt::simd: byte-order reversal moved to 32-bit lanes; two- and four-byte elements reverse within a lane, eight-byte elements bswap both lanes then swap the pair. Unaligned buffers stage through an aligned stack buffer; the elements past a vector block use the scalar loop.
  • nanocesu8::simd: the encode fast-path scan is one Simd-generic loop (equal_u8s/and_u8s/or_m8s + first_true_m8s); simdutf8 still does UTF-8 validation.
  • Dependency change: wide removed; pulp 0.22.3 added with default-features = false, features = ["x86-v3"] (no_std; AVX2 on x86, NEON on aarch64, simd128 on wasm, pulp's scalar backend elsewhere).
  • Lockfiles regenerated for the root workspace and the excluded bench.
  • Scalar-backend unit tests added in both crates, since the scalar path no longer runs on an AVX2 dev machine.

Behavior

  • Bytes, values and errors are unchanged; allocation guarantees hold: one allocation to read a numeric list, none to write one.
  • Note: x86_64 CPUs without AVX2 now use pulp's scalar backend instead of the old baseline-SSE2 code.

Verification

  • cargo test --workspace --all-features in debug and release
  • cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
  • no_std thumbv7em-none-eabi and x86_64-unknown-none clippy + release builds with nanonbt/simd; aarch64-unknown-linux-gnu and wasm32-unknown-unknown compile checks
  • bench workspace cargo clippy --all-targets --locked on the pinned nightly
  • cargo fmt --check, taplo fmt --check, cargo machete, typos

@topi-banana topi-banana self-assigned this Sep 27, 2026
@topi-banana
topi-banana marked this pull request as ready for review September 27, 2026 03:51
The `simd` feature carried its own vector code: a `std::arch` byte-swap
for x86, scalar/NEON/wasm modules for the rest, and `wide` for the
CESU-8 encode scan. Width and dispatch were settled by cfg, so the
feature depended on three hand-rolled backends.

Both modules now implement `pulp`'s `WithSimd` and let `Arch::dispatch`
pick the widest backend the CPU has at run time. Byte-order reversal
stays on 32-bit lanes, the widest integral lane pulp shifts by a
runtime amount: two- and four-byte elements reverse within a lane, an
eight-byte element bswaps its two lanes and then swaps them with each
other. Buffers that are not four-byte aligned are staged through an
aligned stack buffer, and the elements a vector block does not cover
fall back to the scalar loop.

pulp is taken with `default-features = false, features = ["x86-v3"]`,
so the feature stays no_std and gains AVX2 dispatch on x86, NEON on
aarch64 and simd128 on wasm, with pulp's scalar backend elsewhere.
`simdutf8` stays for the UTF-8 check. `wide` is gone.

Allocation behavior is unchanged: reading a numeric list is still one
allocation (copy into the `Vec`, then swap there) and writing one is
still none (the write side swaps its stack chunk before handing it to
the writer). The scalar backend no longer runs on an AVX2 host, so both
crates now test it directly.
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Benchmark results

2346847a (this pull request) against dce75dde (main). Workflow run.

Every counting platform compares its own base and pull request; a count is exact on the platform that produced it, but counts from different architectures are different instruction sets and are not comparable with each other. pumpkin entries are listed for reference only: their compounds are std hash maps, so their counts move between runs with the seed the map is built under.

Platforms

Platform Harness Entries 🟢 🔴 ⚪ Other
linux-x86_64 callgrind instructions 202 60 33 80 29 reference
linux-aarch64 callgrind instructions 202 40 36 97 29 reference
wasm32-wasip1 wasmi fuel 144 19 61 35 29 reference
windows-x64 build & run 202 run — — — —
windows-arm64 build & run 202 run — — — —
macos-x64 build & run 202 run — — — —
macos-arm64 build & run 202 run — — — —

linux-x86_64

Callgrind instruction counts: exact within this platform, so the two sides compare without a threshold; lower is better.

60 improved · 33 regressed · 80 unchanged of 173 entries compared — 29 reference.

Improved

Benchmark main PR Change
parse/nanonbt-derive/int-array 1375950 688512 🟢 -50.0%
parse/nanonbt-derive-signed/int-array 1375968 688535 🟢 -50.0%
parse/nanonbt-derive-signed/short-list 563498 344800 🟢 -38.8%
parse/nanonbt-derive/short-list 563484 344795 🟢 -38.8%
write/nanonbt-derive-signed/int-array 2193240 1419840 🟢 -35.3%
write/nanonbt-derive/int-array 2099544 1365200 🟢 -35.0%
parse/nanonbt-derive/long-array 2750949 2063503 🟢 -25.0%
parse/nanonbt-derive-signed/long-array 2750965 2063535 🟢 -25.0%
write/nanonbt-derive-signed/short-list 899621 704341 🟢 -21.7%
write/nanonbt-derive/short-list 864520 677056 🟢 -21.7%
write/nanonbt-derive-signed/long-array 4593768 3765660 🟢 -18.0%
write/nanonbt-derive/long-array 4406330 3656338 🟢 -17.0%
parse/nanonbt-derive/long-names 17401 15549 🟢 -10.6%
parse/nanonbt-derive/short-names 14941 14059 🟢 -5.9%
parse/nanonbt-borrow-signed/short-list 428 412 🟢 -3.7%
parse/nanonbt-borrow/short-list 428 412 🟢 -3.7%
parse/nanonbt-borrow-signed/int-array 423 410 🟢 -3.1%
parse/nanonbt-borrow-signed/long-array 423 410 🟢 -3.1%
parse/nanonbt-borrow/int-array 423 410 🟢 -3.1%
parse/nanonbt-borrow/long-array 423 410 🟢 -3.1%
parse/nanonbt-borrow/small 2629 2549 🟢 -3.0%
skip/nanonbt-derive/byte-array 682 662 🟢 -2.9%
skip/nanonbt-derive/int-array 682 662 🟢 -2.9%
skip/nanonbt-derive/long-array 683 663 🟢 -2.9%
parse/nanonbt-borrow-signed/byte-array 419 407 🟢 -2.9%
parse/nanonbt-borrow/byte-array 419 407 🟢 -2.9%
skip/nanonbt-derive/byte-list 705 685 🟢 -2.8%
skip/nanonbt-derive/short-list 705 685 🟢 -2.8%
skip/nanonbt-derive/double-list 706 686 🟢 -2.8%
skip/nanonbt-derive/float-list 706 686 🟢 -2.8%
skip/nanonbt-derive/int-list 706 686 🟢 -2.8%
skip/nanonbt-derive/long-list 706 686 🟢 -2.8%
parse/nanonbt-derive/small 2798 2732 🟢 -2.4%
parse/nanonbt-serde/long-names 77392 76690 🟢 -0.9%
skip/nanonbt-serde/byte-array 965 957 🟢 -0.8%
skip/nanonbt-serde/int-array 965 957 🟢 -0.8%
skip/nanonbt-serde/long-array 966 958 🟢 -0.8%
skip/nanonbt-serde/byte-list 988 980 🟢 -0.8%
skip/nanonbt-serde/short-list 988 980 🟢 -0.8%
skip/nanonbt-serde/double-list 989 981 🟢 -0.8%
skip/nanonbt-serde/float-list 989 981 🟢 -0.8%
skip/nanonbt-serde/int-list 989 981 🟢 -0.8%
skip/nanonbt-serde/long-list 989 981 🟢 -0.8%
write/nanonbt-serde/long-names 32488 32240 🟢 -0.8%
parse/nanonbt-serde/player 247791 246003 🟢 -0.7%
parse/nanonbt-borrow/player 185187 184286 🟢 -0.5%
parse/nanonbt-serde/chunk 310681 309198 🟢 -0.5%
write/nanonbt-derive/chunk 123503 123229 🟢 -0.2%
parse/nanonbt-derive/player 193632 193208 🟢 -0.2%
parse/simdnbt-borrow/chunk 160245 160125 🟢 -0.1%
parse/simdnbt-borrow/short-names 114386 114314 🟢 -0.1%
parse/simdnbt-owned/chunk 386642 386476 🟢 0.0%
write/fastnbt/player 303897 303836 🟢 0.0%
parse/fastnbt/chunk 333617 333576 🟢 0.0%
parse/nanonbt-derive/byte-array 500984 500971 🟢 0.0%
parse/nanonbt-derive-signed/byte-array 501010 500998 🟢 0.0%
skip/nanonbt-derive/string-list 4500717 4500697 🟢 0.0%
skip/nanonbt-derive/compound-list 11200717 11200697 🟢 0.0%
skip/nanonbt-serde/string-list 4501000 4500992 🟢 0.0%
skip/nanonbt-serde/compound-list 11201000 11200992 🟢 0.0%

Regressed

Benchmark main PR Change
write/nanonbt-borrow/chunk 84628 88658 🔴 +4.8%
write/nanonbt-serde/chunk 216560 224705 🔴 +3.8%
write/nanonbt-serde/player 218558 224198 🔴 +2.6%
write/nanonbt-borrow/small 1824 1871 🔴 +2.6%
write/nanonbt-serde/small 5339 5473 🔴 +2.5%
write/nanonbt-serde/short-names 31417 32129 🔴 +2.3%
write/nanonbt-derive/player 105112 107208 🔴 +2.0%
write/nanonbt-borrow/player 98188 100097 🔴 +1.9%
parse/nanonbt-borrow/chunk 172865 176219 🔴 +1.9%
write/nanonbt-derive/small 2161 2196 🔴 +1.6%
parse/nanonbt-serde/short-names 81491 82547 🔴 +1.3%
parse/fastnbt/short-names 77183 78080 🔴 +1.2%
parse/fastnbt/small 2979 2996 🔴 +0.6%
parse/simdnbt-borrow/small 3118 3135 🔴 +0.5%
parse/nanonbt-derive/chunk 267722 268964 🔴 +0.5%
parse/nanonbt-serde/small 4205 4216 🔴 +0.3%
write/nanonbt-derive/short-names 7183 7191 🔴 +0.1%
write/nanonbt-derive/long-names 7240 7248 🔴 +0.1%
parse/simdnbt-borrow/player 129724 129866 🔴 +0.1%
parse/fastnbt/player 154467 154615 🔴 +0.1%
parse/simdnbt-owned/short-names 104869 104953 🔴 +0.1%
parse/simdnbt-owned/player 261154 261223 🔴 0.0%
write/nanonbt-borrow-signed/int-array 441610 441630 🔴 0.0%
write/nanonbt-borrow/int-array 441610 441630 🔴 0.0%
write/nanonbt-derive-signed/byte-array 501988 502010 🔴 0.0%
write/nanonbt-borrow-signed/long-array 881604 881624 🔴 0.0%
write/nanonbt-borrow/long-array 881604 881624 🔴 0.0%
write/nanonbt-borrow-signed/byte-array 1001511 1001533 🔴 0.0%
write/nanonbt-borrow/byte-array 1001511 1001533 🔴 0.0%
write/nanonbt-derive/byte-array 502108 502116 🔴 0.0%
write/fastnbt-borrow/long-array 883594 883606 🔴 0.0%
write/nanonbt-borrow-signed/short-list 2001552 2001574 🔴 0.0%
write/nanonbt-borrow/short-list 2001552 2001574 🔴 0.0%
All 202 entries · 80 unchanged omitted

parse

Benchmark PR Change
parse/fastnbt/chunk 333576 🟢 0.0%
parse/fastnbt/player 154615 🔴 +0.1%
parse/fastnbt/short-names 78080 🔴 +1.2%
parse/fastnbt/small 2996 🔴 +0.6%
parse/nanonbt-borrow-signed/byte-array 407 🟢 -2.9%
parse/nanonbt-borrow-signed/int-array 410 🟢 -3.1%
parse/nanonbt-borrow-signed/long-array 410 🟢 -3.1%
parse/nanonbt-borrow-signed/short-list 412 🟢 -3.7%
parse/nanonbt-borrow/byte-array 407 🟢 -2.9%
parse/nanonbt-borrow/chunk 176219 🔴 +1.9%
parse/nanonbt-borrow/int-array 410 🟢 -3.1%
parse/nanonbt-borrow/long-array 410 🟢 -3.1%
parse/nanonbt-borrow/player 184286 🟢 -0.5%
parse/nanonbt-borrow/short-list 412 🟢 -3.7%
parse/nanonbt-borrow/small 2549 🟢 -3.0%
parse/nanonbt-derive-signed/byte-array 500998 🟢 0.0%
parse/nanonbt-derive-signed/int-array 688535 🟢 -50.0%
parse/nanonbt-derive-signed/long-array 2063535 🟢 -25.0%
parse/nanonbt-derive-signed/short-list 344800 🟢 -38.8%
parse/nanonbt-derive/byte-array 500971 🟢 0.0%
parse/nanonbt-derive/chunk 268964 🔴 +0.5%
parse/nanonbt-derive/int-array 688512 🟢 -50.0%
parse/nanonbt-derive/long-array 2063503 🟢 -25.0%
parse/nanonbt-derive/long-names 15549 🟢 -10.6%
parse/nanonbt-derive/player 193208 🟢 -0.2%
parse/nanonbt-derive/short-list 344795 🟢 -38.8%
parse/nanonbt-derive/short-names 14059 🟢 -5.9%
parse/nanonbt-derive/small 2732 🟢 -2.4%
parse/nanonbt-serde/chunk 309198 🟢 -0.5%
parse/nanonbt-serde/long-names 76690 🟢 -0.9%
parse/nanonbt-serde/player 246003 🟢 -0.7%
parse/nanonbt-serde/short-names 82547 🔴 +1.3%
parse/nanonbt-serde/small 4216 🔴 +0.3%
parse/pumpkin/byte-array 1002673 not compared
parse/pumpkin/chunk 728101 not compared
parse/pumpkin/int-array 1880265 not compared
parse/pumpkin/long-array 2570251 not compared
parse/pumpkin/long-names 141916 not compared
parse/pumpkin/player 520469 not compared
parse/pumpkin/short-list 79422793 not compared
parse/pumpkin/short-names 99385 not compared
parse/pumpkin/small 12894 not compared
parse/simdnbt-borrow/chunk 160125 🟢 -0.1%
parse/simdnbt-borrow/player 129866 🔴 +0.1%
parse/simdnbt-borrow/short-names 114314 🟢 -0.1%
parse/simdnbt-borrow/small 3135 🔴 +0.5%
parse/simdnbt-owned/chunk 386476 🟢 0.0%
parse/simdnbt-owned/player 261223 🔴 0.0%
parse/simdnbt-owned/short-names 104953 🔴 +0.1%

skip

Benchmark PR Change
skip/nanonbt-derive/byte-array 662 🟢 -2.9%
skip/nanonbt-derive/byte-list 685 🟢 -2.8%
skip/nanonbt-derive/compound-list 11200697 🟢 0.0%
skip/nanonbt-derive/double-list 686 🟢 -2.8%
skip/nanonbt-derive/float-list 686 🟢 -2.8%
skip/nanonbt-derive/int-array 662 🟢 -2.9%
skip/nanonbt-derive/int-list 686 🟢 -2.8%
skip/nanonbt-derive/long-array 663 🟢 -2.9%
skip/nanonbt-derive/long-list 686 🟢 -2.8%
skip/nanonbt-derive/short-list 685 🟢 -2.8%
skip/nanonbt-derive/string-list 4500697 🟢 0.0%
skip/nanonbt-serde/byte-array 957 🟢 -0.8%
skip/nanonbt-serde/byte-list 980 🟢 -0.8%
skip/nanonbt-serde/compound-list 11200992 🟢 0.0%
skip/nanonbt-serde/double-list 981 🟢 -0.8%
skip/nanonbt-serde/float-list 981 🟢 -0.8%
skip/nanonbt-serde/int-array 957 🟢 -0.8%
skip/nanonbt-serde/int-list 981 🟢 -0.8%
skip/nanonbt-serde/long-array 958 🟢 -0.8%
skip/nanonbt-serde/long-list 981 🟢 -0.8%
skip/nanonbt-serde/short-list 980 🟢 -0.8%
skip/nanonbt-serde/string-list 4500992 🟢 0.0%
skip/pumpkin/byte-array 103203 not compared
skip/pumpkin/byte-list 14504198 not compared
skip/pumpkin/compound-list 169296415 not compared
skip/pumpkin/double-list 15563473 not compared
skip/pumpkin/float-list 15333639 not compared
skip/pumpkin/int-array 690357 not compared
skip/pumpkin/int-list 15333639 not compared
skip/pumpkin/long-array 1140349 not compared
skip/pumpkin/long-list 15563473 not compared
skip/pumpkin/short-list 15103798 not compared
skip/pumpkin/string-list 84420962 not compared

write

Benchmark PR Change
write/fastnbt-borrow/long-array 883606 🔴 0.0%
write/fastnbt/player 303836 🟢 0.0%
write/nanonbt-borrow-signed/byte-array 1001533 🔴 0.0%
write/nanonbt-borrow-signed/int-array 441630 🔴 0.0%
write/nanonbt-borrow-signed/long-array 881624 🔴 0.0%
write/nanonbt-borrow-signed/short-list 2001574 🔴 0.0%
write/nanonbt-borrow/byte-array 1001533 🔴 0.0%
write/nanonbt-borrow/chunk 88658 🔴 +4.8%
write/nanonbt-borrow/int-array 441630 🔴 0.0%
write/nanonbt-borrow/long-array 881624 🔴 0.0%
write/nanonbt-borrow/player 100097 🔴 +1.9%
write/nanonbt-borrow/short-list 2001574 🔴 0.0%
write/nanonbt-borrow/small 1871 🔴 +2.6%
write/nanonbt-derive-signed/byte-array 502010 🔴 0.0%
write/nanonbt-derive-signed/int-array 1419840 🟢 -35.3%
write/nanonbt-derive-signed/long-array 3765660 🟢 -18.0%
write/nanonbt-derive-signed/short-list 704341 🟢 -21.7%
write/nanonbt-derive/byte-array 502116 🔴 0.0%
write/nanonbt-derive/chunk 123229 🟢 -0.2%
write/nanonbt-derive/int-array 1365200 🟢 -35.0%
write/nanonbt-derive/long-array 3656338 🟢 -17.0%
write/nanonbt-derive/long-names 7248 🔴 +0.1%
write/nanonbt-derive/player 107208 🔴 +2.0%
write/nanonbt-derive/short-list 677056 🟢 -21.7%
write/nanonbt-derive/short-names 7191 🔴 +0.1%
write/nanonbt-derive/small 2196 🔴 +1.6%
write/nanonbt-serde/chunk 224705 🔴 +3.8%
write/nanonbt-serde/long-names 32240 🟢 -0.8%
write/nanonbt-serde/player 224198 🔴 +2.6%
write/nanonbt-serde/short-names 32129 🔴 +2.3%
write/nanonbt-serde/small 5473 🔴 +2.5%
write/pumpkin/byte-array 1003849 not compared
write/pumpkin/chunk 644988 not compared
write/pumpkin/int-array 6727874 not compared
write/pumpkin/long-array 7951683 not compared
write/pumpkin/long-names 148266 not compared
write/pumpkin/player 499192 not compared
write/pumpkin/short-list 45772895 not compared
write/pumpkin/short-names 86686 not compared
write/pumpkin/small 10977 not compared

linux-aarch64

Callgrind instruction counts: exact within this platform, so the two sides compare without a threshold; lower is better.

40 improved · 36 regressed · 97 unchanged of 173 entries compared — 29 reference.

Improved

Benchmark main PR Change
write/nanonbt-borrow/chunk 8868 7097 🟢 -20.0%
write/nanonbt-derive/chunk 117641 105755 🟢 -10.1%
parse/nanonbt-borrow/small 2101 1929 🟢 -8.2%
parse/nanonbt-borrow/chunk 146267 134372 🟢 -8.1%
parse/nanonbt-derive/small 2293 2126 🟢 -7.3%
write/nanonbt-borrow/player 105736 98777 🟢 -6.6%
write/nanonbt-derive/player 113574 106732 🟢 -6.0%
write/nanonbt-derive/small 2234 2123 🟢 -5.0%
skip/nanonbt-derive/int-array 590 567 🟢 -3.9%
skip/nanonbt-derive/byte-array 591 568 🟢 -3.9%
skip/nanonbt-derive/long-array 591 568 🟢 -3.9%
skip/nanonbt-derive/byte-list 606 583 🟢 -3.8%
skip/nanonbt-derive/long-list 607 584 🟢 -3.8%
skip/nanonbt-derive/float-list 609 586 🟢 -3.8%
skip/nanonbt-derive/short-list 609 586 🟢 -3.8%
skip/nanonbt-derive/double-list 611 588 🟢 -3.8%
skip/nanonbt-derive/int-list 611 588 🟢 -3.8%
parse/nanonbt-borrow-signed/short-list 386 373 🟢 -3.4%
parse/nanonbt-borrow/short-list 386 373 🟢 -3.4%
write/nanonbt-serde/player 218211 211150 🟢 -3.2%
parse/nanonbt-serde/chunk 273308 264492 🟢 -3.2%
write/nanonbt-serde/chunk 183782 178037 🟢 -3.1%
parse/nanonbt-borrow/player 157985 153740 🟢 -2.7%
parse/nanonbt-derive/player 168516 164191 🟢 -2.6%
parse/nanonbt-serde/player 217929 212618 🟢 -2.4%
parse/nanonbt-derive/chunk 237831 232476 🟢 -2.3%
write/nanonbt-serde/small 5269 5158 🟢 -2.1%
parse/nanonbt-borrow-signed/byte-array 387 381 🟢 -1.6%
parse/nanonbt-borrow/byte-array 387 381 🟢 -1.6%
parse/nanonbt-borrow-signed/int-array 390 384 🟢 -1.5%
parse/nanonbt-borrow-signed/long-array 390 384 🟢 -1.5%
parse/nanonbt-borrow/int-array 390 384 🟢 -1.5%
parse/nanonbt-borrow/long-array 390 384 🟢 -1.5%
parse/nanonbt-derive/short-names 11198 11112 🟢 -0.8%
parse/nanonbt-serde/small 3502 3479 🟢 -0.7%
parse/nanonbt-serde/short-names 75961 75706 🟢 -0.3%
parse/nanonbt-derive/byte-array 63488 63473 🟢 0.0%
parse/nanonbt-derive-signed/byte-array 63513 63505 🟢 0.0%
skip/nanonbt-derive/string-list 4300625 4300602 🟢 0.0%
skip/nanonbt-derive/compound-list 11000625 11000602 🟢 0.0%

Regressed

Benchmark main PR Change
parse/nanonbt-derive/short-list 375994 719789 🔴 +91.4%
parse/nanonbt-derive-signed/short-list 376014 719809 🔴 +91.4%
parse/nanonbt-derive-signed/long-array 1500982 2126039 🔴 +41.6%
parse/nanonbt-derive/long-array 1500961 2126001 🔴 +41.6%
write/nanonbt-derive/short-list 817883 1118686 🔴 +36.8%
parse/nanonbt-derive-signed/int-array 750987 938544 🔴 +25.0%
parse/nanonbt-derive/int-array 750962 938506 🔴 +25.0%
write/nanonbt-derive-signed/long-array 3486500 3939628 🔴 +13.0%
write/nanonbt-derive/long-array 3470897 3908396 🔴 +12.6%
write/nanonbt-derive-signed/int-array 1623205 1748224 🔴 +7.7%
write/nanonbt-derive/int-array 1615414 1732616 🔴 +7.3%
parse/nanonbt-derive/long-names 15674 16554 🔴 +5.6%
write/nanonbt-serde/long-names 32659 34067 🔴 +4.3%
write/nanonbt-borrow-signed/short-list 240 246 🔴 +2.5%
write/nanonbt-borrow/short-list 240 246 🔴 +2.5%
write/nanonbt-derive-signed/short-list 240 246 🔴 +2.5%
write/nanonbt-borrow/small 244 249 🔴 +2.0%
parse/nanonbt-serde/long-names 127894 128855 🔴 +0.8%
skip/nanonbt-serde/byte-array 826 827 🔴 +0.1%
skip/nanonbt-serde/int-array 826 827 🔴 +0.1%
skip/nanonbt-serde/long-array 826 827 🔴 +0.1%
skip/nanonbt-serde/byte-list 842 843 🔴 +0.1%
skip/nanonbt-serde/long-list 843 844 🔴 +0.1%
skip/nanonbt-serde/float-list 845 846 🔴 +0.1%
skip/nanonbt-serde/short-list 845 846 🔴 +0.1%
skip/nanonbt-serde/double-list 847 848 🔴 +0.1%
skip/nanonbt-serde/int-list 847 848 🔴 +0.1%
write/nanonbt-derive-signed/byte-array 64033 64038 🔴 0.0%
write/nanonbt-borrow-signed/byte-array 126054 126059 🔴 0.0%
write/nanonbt-borrow/byte-array 126054 126059 🔴 0.0%
write/nanonbt-borrow-signed/int-array 501066 501071 🔴 0.0%
write/nanonbt-borrow/int-array 501066 501071 🔴 0.0%
write/nanonbt-borrow-signed/long-array 1001066 1001071 🔴 0.0%
write/nanonbt-borrow/long-array 1001066 1001071 🔴 0.0%
skip/nanonbt-serde/string-list 4400861 4400862 🔴 0.0%
skip/nanonbt-serde/compound-list 11000861 11000862 🔴 0.0%
All 202 entries · 97 unchanged omitted

parse

Benchmark PR Change
parse/nanonbt-borrow-signed/byte-array 381 🟢 -1.6%
parse/nanonbt-borrow-signed/int-array 384 🟢 -1.5%
parse/nanonbt-borrow-signed/long-array 384 🟢 -1.5%
parse/nanonbt-borrow-signed/short-list 373 🟢 -3.4%
parse/nanonbt-borrow/byte-array 381 🟢 -1.6%
parse/nanonbt-borrow/chunk 134372 🟢 -8.1%
parse/nanonbt-borrow/int-array 384 🟢 -1.5%
parse/nanonbt-borrow/long-array 384 🟢 -1.5%
parse/nanonbt-borrow/player 153740 🟢 -2.7%
parse/nanonbt-borrow/short-list 373 🟢 -3.4%
parse/nanonbt-borrow/small 1929 🟢 -8.2%
parse/nanonbt-derive-signed/byte-array 63505 🟢 0.0%
parse/nanonbt-derive-signed/int-array 938544 🔴 +25.0%
parse/nanonbt-derive-signed/long-array 2126039 🔴 +41.6%
parse/nanonbt-derive-signed/short-list 719809 🔴 +91.4%
parse/nanonbt-derive/byte-array 63473 🟢 0.0%
parse/nanonbt-derive/chunk 232476 🟢 -2.3%
parse/nanonbt-derive/int-array 938506 🔴 +25.0%
parse/nanonbt-derive/long-array 2126001 🔴 +41.6%
parse/nanonbt-derive/long-names 16554 🔴 +5.6%
parse/nanonbt-derive/player 164191 🟢 -2.6%
parse/nanonbt-derive/short-list 719789 🔴 +91.4%
parse/nanonbt-derive/short-names 11112 🟢 -0.8%
parse/nanonbt-derive/small 2126 🟢 -7.3%
parse/nanonbt-serde/chunk 264492 🟢 -3.2%
parse/nanonbt-serde/long-names 128855 🔴 +0.8%
parse/nanonbt-serde/player 212618 🟢 -2.4%
parse/nanonbt-serde/short-names 75706 🟢 -0.3%
parse/nanonbt-serde/small 3479 🟢 -0.7%
parse/pumpkin/byte-array 127838 not compared
parse/pumpkin/chunk 701903 not compared
parse/pumpkin/int-array 940311 not compared
parse/pumpkin/long-array 1877849 not compared
parse/pumpkin/long-names 125270 not compared
parse/pumpkin/player 502351 not compared
parse/pumpkin/short-list 77120271 not compared
parse/pumpkin/short-names 90626 not compared
parse/pumpkin/small 12060 not compared

skip

Benchmark PR Change
skip/nanonbt-derive/byte-array 568 🟢 -3.9%
skip/nanonbt-derive/byte-list 583 🟢 -3.8%
skip/nanonbt-derive/compound-list 11000602 🟢 0.0%
skip/nanonbt-derive/double-list 588 🟢 -3.8%
skip/nanonbt-derive/float-list 586 🟢 -3.8%
skip/nanonbt-derive/int-array 567 🟢 -3.9%
skip/nanonbt-derive/int-list 588 🟢 -3.8%
skip/nanonbt-derive/long-array 568 🟢 -3.9%
skip/nanonbt-derive/long-list 584 🟢 -3.8%
skip/nanonbt-derive/short-list 586 🟢 -3.8%
skip/nanonbt-derive/string-list 4300602 🟢 0.0%
skip/nanonbt-serde/byte-array 827 🔴 +0.1%
skip/nanonbt-serde/byte-list 843 🔴 +0.1%
skip/nanonbt-serde/compound-list 11000862 🔴 0.0%
skip/nanonbt-serde/double-list 848 🔴 +0.1%
skip/nanonbt-serde/float-list 846 🔴 +0.1%
skip/nanonbt-serde/int-array 827 🔴 +0.1%
skip/nanonbt-serde/int-list 848 🔴 +0.1%
skip/nanonbt-serde/long-array 827 🔴 +0.1%
skip/nanonbt-serde/long-list 844 🔴 +0.1%
skip/nanonbt-serde/short-list 846 🔴 +0.1%
skip/nanonbt-serde/string-list 4400862 🔴 0.0%
skip/pumpkin/byte-array 15598 not compared
skip/pumpkin/byte-list 14104236 not compared
skip/pumpkin/compound-list 162658371 not compared
skip/pumpkin/double-list 14562163 not compared
skip/pumpkin/float-list 14533005 not compared
skip/pumpkin/int-array 140321 not compared
skip/pumpkin/int-list 14633005 not compared
skip/pumpkin/long-array 277821 not compared
skip/pumpkin/long-list 14662163 not compared
skip/pumpkin/short-list 14603867 not compared
skip/pumpkin/string-list 81865293 not compared

write

Benchmark PR Change
write/nanonbt-borrow-signed/byte-array 126059 🔴 0.0%
write/nanonbt-borrow-signed/int-array 501071 🔴 0.0%
write/nanonbt-borrow-signed/long-array 1001071 🔴 0.0%
write/nanonbt-borrow-signed/short-list 246 🔴 +2.5%
write/nanonbt-borrow/byte-array 126059 🔴 0.0%
write/nanonbt-borrow/chunk 7097 🟢 -20.0%
write/nanonbt-borrow/int-array 501071 🔴 0.0%
write/nanonbt-borrow/long-array 1001071 🔴 0.0%
write/nanonbt-borrow/player 98777 🟢 -6.6%
write/nanonbt-borrow/short-list 246 🔴 +2.5%
write/nanonbt-borrow/small 249 🔴 +2.0%
write/nanonbt-derive-signed/byte-array 64038 🔴 0.0%
write/nanonbt-derive-signed/int-array 1748224 🔴 +7.7%
write/nanonbt-derive-signed/long-array 3939628 🔴 +13.0%
write/nanonbt-derive-signed/short-list 246 🔴 +2.5%
write/nanonbt-derive/chunk 105755 🟢 -10.1%
write/nanonbt-derive/int-array 1732616 🔴 +7.3%
write/nanonbt-derive/long-array 3908396 🔴 +12.6%
write/nanonbt-derive/player 106732 🟢 -6.0%
write/nanonbt-derive/short-list 1118686 🔴 +36.8%
write/nanonbt-derive/small 2123 🟢 -5.0%
write/nanonbt-serde/chunk 178037 🟢 -3.1%
write/nanonbt-serde/long-names 34067 🔴 +4.3%
write/nanonbt-serde/player 211150 🟢 -3.2%
write/nanonbt-serde/small 5158 🟢 -2.1%
write/pumpkin/byte-array 129029 not compared
write/pumpkin/chunk 607062 not compared
write/pumpkin/int-array 250223 not compared
write/pumpkin/long-array 500223 not compared
write/pumpkin/long-names 1009 not compared
write/pumpkin/player 224710 not compared
write/pumpkin/short-list 42044096 not compared
write/pumpkin/short-names 773 not compared
write/pumpkin/small 9840 not compared

wasm32-wasip1

Wasmi fuel: the wasm instructions each entry runs, exact within this platform, so the two sides compare without a threshold; lower is better.

19 improved · 61 regressed · 35 unchanged of 115 entries compared — 29 reference.

Improved

Benchmark main PR Change
write/nanonbt-borrow/chunk 109308 92996 🟢 -14.9%
write/nanonbt-derive/chunk 94818 82104 🟢 -13.4%
parse/nanonbt-derive-signed/int-array 1009775 916126 🟢 -9.3%
parse/nanonbt-derive/int-array 1014567 921620 🟢 -9.2%
write/nanonbt-derive/player 198805 191133 🟢 -3.9%
write/nanonbt-borrow/player 222723 214904 🟢 -3.5%
parse/nanonbt-borrow/chunk 427018 413996 🟢 -3.0%
write/nanonbt-derive/small 5345 5222 🟢 -2.3%
parse/nanonbt-derive/chunk 648482 640044 🟢 -1.3%
parse/nanonbt-serde/chunk 1290425 1276040 🟢 -1.1%
parse/nanonbt-derive/player 751165 743988 🟢 -1.0%
write/nanonbt-borrow/small 14008 13885 🟢 -0.9%
parse/nanonbt-borrow/player 660741 657453 🟢 -0.5%
parse/nanonbt-borrow/small 24216 24139 🟢 -0.3%
parse/nanonbt-derive/small 33308 33231 🟢 -0.2%
parse/nanonbt-serde/player 1298782 1296182 🟢 -0.2%
write/nanonbt-serde/chunk 502673 501714 🟢 -0.2%
write/nanonbt-serde/small 56701 56610 🟢 -0.2%
write/nanonbt-serde/player 674890 673917 🟢 -0.1%

Regressed

Benchmark main PR Change
write/nanonbt-derive/short-list 852089 1113838 🔴 +30.7%
write/nanonbt-derive-signed/short-list 870773 1132522 🔴 +30.1%
parse/nanonbt-derive-signed/long-array 2009784 2572290 🔴 +28.0%
parse/nanonbt-derive/long-array 2013830 2574803 🔴 +27.9%
parse/nanonbt-derive/short-list 517053 661038 🔴 +27.8%
parse/nanonbt-derive-signed/short-list 509832 650585 🔴 +27.6%
write/nanonbt-derive/long-array 3086902 3758781 🔴 +21.8%
write/nanonbt-derive-signed/long-array 3151716 3823595 🔴 +21.3%
write/nanonbt-derive/int-array 1578861 1766385 🔴 +11.9%
write/nanonbt-derive-signed/int-array 1612427 1799951 🔴 +11.6%
parse/nanonbt-derive/long-names 141408 142432 🔴 +0.7%
write/nanonbt-serde/long-names 129019 129919 🔴 +0.7%
skip/nanonbt-derive/byte-array 2784 2796 🔴 +0.4%
skip/nanonbt-derive/int-array 2784 2796 🔴 +0.4%
skip/nanonbt-derive/long-array 2784 2796 🔴 +0.4%
skip/nanonbt-derive/double-list 2841 2853 🔴 +0.4%
skip/nanonbt-derive/float-list 2841 2853 🔴 +0.4%
parse/nanonbt-derive/short-names 128187 128571 🔴 +0.3%
parse/nanonbt-borrow-signed/byte-array 2021 2027 🔴 +0.3%
parse/nanonbt-borrow-signed/int-array 2033 2039 🔴 +0.3%
parse/nanonbt-borrow-signed/long-array 2033 2039 🔴 +0.3%
parse/nanonbt-borrow-signed/short-list 2041 2047 🔴 +0.3%
skip/nanonbt-serde/byte-array 4211 4223 🔴 +0.3%
skip/nanonbt-serde/int-array 4211 4223 🔴 +0.3%
skip/nanonbt-serde/long-array 4211 4223 🔴 +0.3%
skip/nanonbt-serde/double-list 4268 4280 🔴 +0.3%
skip/nanonbt-serde/float-list 4268 4280 🔴 +0.3%
parse/nanonbt-serde/small 147279 147650 🔴 +0.3%
skip/nanonbt-derive/short-list 4921 4933 🔴 +0.2%
skip/nanonbt-derive/int-list 5200 5212 🔴 +0.2%
skip/nanonbt-derive/long-list 5200 5212 🔴 +0.2%
write/nanonbt-serde/short-names 127232 127492 🔴 +0.2%
parse/nanonbt-serde/long-names 534886 535910 🔴 +0.2%
skip/nanonbt-serde/short-list 6348 6360 🔴 +0.2%
skip/nanonbt-serde/int-list 6627 6639 🔴 +0.2%
skip/nanonbt-serde/long-list 6627 6639 🔴 +0.2%
parse/nanonbt-serde/short-names 373642 374026 🔴 +0.1%
parse/nanonbt-borrow/byte-array 8328 8334 🔴 +0.1%
parse/nanonbt-borrow/int-array 8620 8626 🔴 +0.1%
parse/nanonbt-borrow/long-array 8620 8626 🔴 +0.1%
parse/nanonbt-borrow/short-list 8628 8634 🔴 +0.1%
skip/nanonbt-derive/byte-list 24275 24287 🔴 0.0%
skip/nanonbt-serde/byte-list 25555 25567 🔴 0.0%
parse/nanonbt-derive-signed/byte-array 17497 17503 🔴 0.0%
write/nanonbt-derive/short-names 12859 12863 🔴 0.0%
write/nanonbt-derive/long-names 13174 13178 🔴 0.0%
write/nanonbt-derive/byte-array 13179 13183 🔴 0.0%
parse/nanonbt-derive/byte-array 20086 20092 🔴 0.0%
write/nanonbt-derive-signed/byte-array 16580 16584 🔴 0.0%
write/nanonbt-borrow-signed/byte-array 16805 16809 🔴 0.0%
write/nanonbt-borrow/byte-array 16805 16809 🔴 0.0%
write/nanonbt-borrow-signed/short-list 25055 25059 🔴 0.0%
write/nanonbt-borrow/short-list 25055 25059 🔴 0.0%
write/nanonbt-borrow-signed/int-array 40265 40269 🔴 0.0%
write/nanonbt-borrow/int-array 40265 40269 🔴 0.0%
write/nanonbt-borrow-signed/long-array 71515 71519 🔴 0.0%
write/nanonbt-borrow/long-array 71515 71519 🔴 0.0%
skip/nanonbt-derive/string-list 28405105 28405117 🔴 0.0%
skip/nanonbt-serde/string-list 28806532 28806544 🔴 0.0%
skip/nanonbt-derive/compound-list 64402830 64402842 🔴 0.0%
skip/nanonbt-serde/compound-list 65204257 65204269 🔴 0.0%
All 144 entries · 35 unchanged omitted

parse

Benchmark PR Change
parse/nanonbt-borrow-signed/byte-array 2027 🔴 +0.3%
parse/nanonbt-borrow-signed/int-array 2039 🔴 +0.3%
parse/nanonbt-borrow-signed/long-array 2039 🔴 +0.3%
parse/nanonbt-borrow-signed/short-list 2047 🔴 +0.3%
parse/nanonbt-borrow/byte-array 8334 🔴 +0.1%
parse/nanonbt-borrow/chunk 413996 🟢 -3.0%
parse/nanonbt-borrow/int-array 8626 🔴 +0.1%
parse/nanonbt-borrow/long-array 8626 🔴 +0.1%
parse/nanonbt-borrow/player 657453 🟢 -0.5%
parse/nanonbt-borrow/short-list 8634 🔴 +0.1%
parse/nanonbt-borrow/small 24139 🟢 -0.3%
parse/nanonbt-derive-signed/byte-array 17503 🔴 0.0%
parse/nanonbt-derive-signed/int-array 916126 🟢 -9.3%
parse/nanonbt-derive-signed/long-array 2572290 🔴 +28.0%
parse/nanonbt-derive-signed/short-list 650585 🔴 +27.6%
parse/nanonbt-derive/byte-array 20092 🔴 0.0%
parse/nanonbt-derive/chunk 640044 🟢 -1.3%
parse/nanonbt-derive/int-array 921620 🟢 -9.2%
parse/nanonbt-derive/long-array 2574803 🔴 +27.9%
parse/nanonbt-derive/long-names 142432 🔴 +0.7%
parse/nanonbt-derive/player 743988 🟢 -1.0%
parse/nanonbt-derive/short-list 661038 🔴 +27.8%
parse/nanonbt-derive/short-names 128571 🔴 +0.3%
parse/nanonbt-derive/small 33231 🟢 -0.2%
parse/nanonbt-serde/chunk 1276040 🟢 -1.1%
parse/nanonbt-serde/long-names 535910 🔴 +0.2%
parse/nanonbt-serde/player 1296182 🟢 -0.2%
parse/nanonbt-serde/short-names 374026 🔴 +0.1%
parse/nanonbt-serde/small 147650 🔴 +0.3%
parse/pumpkin/byte-array 25626 not compared
parse/pumpkin/chunk 1978432 not compared
parse/pumpkin/int-array 947806 not compared
parse/pumpkin/long-array 12260305 not compared
parse/pumpkin/long-names 350713 not compared
parse/pumpkin/player 1533041 not compared
parse/pumpkin/short-list 373690101 not compared
parse/pumpkin/short-names 263826 not compared
parse/pumpkin/small 136748 not compared

skip

Benchmark PR Change
skip/nanonbt-derive/byte-array 2796 🔴 +0.4%
skip/nanonbt-derive/byte-list 24287 🔴 0.0%
skip/nanonbt-derive/compound-list 64402842 🔴 0.0%
skip/nanonbt-derive/double-list 2853 🔴 +0.4%
skip/nanonbt-derive/float-list 2853 🔴 +0.4%
skip/nanonbt-derive/int-array 2796 🔴 +0.4%
skip/nanonbt-derive/int-list 5212 🔴 +0.2%
skip/nanonbt-derive/long-array 2796 🔴 +0.4%
skip/nanonbt-derive/long-list 5212 🔴 +0.2%
skip/nanonbt-derive/short-list 4933 🔴 +0.2%
skip/nanonbt-derive/string-list 28405117 🔴 0.0%
skip/nanonbt-serde/byte-array 4223 🔴 +0.3%
skip/nanonbt-serde/byte-list 25567 🔴 0.0%
skip/nanonbt-serde/compound-list 65204269 🔴 0.0%
skip/nanonbt-serde/double-list 4280 🔴 +0.3%
skip/nanonbt-serde/float-list 4280 🔴 +0.3%
skip/nanonbt-serde/int-array 4223 🔴 +0.3%
skip/nanonbt-serde/int-list 6639 🔴 +0.2%
skip/nanonbt-serde/long-array 4223 🔴 +0.3%
skip/nanonbt-serde/long-list 6639 🔴 +0.2%
skip/nanonbt-serde/short-list 6360 🔴 +0.2%
skip/nanonbt-serde/string-list 28806544 🔴 0.0%
skip/pumpkin/byte-array 11752 not compared
skip/pumpkin/byte-list 73354578 not compared
skip/pumpkin/compound-list 484456171 not compared
skip/pumpkin/double-list 73898577 not compared
skip/pumpkin/float-list 73930044 not compared
skip/pumpkin/int-array 191481 not compared
skip/pumpkin/int-list 73930044 not compared
skip/pumpkin/long-array 2447730 not compared
skip/pumpkin/long-list 73898577 not compared
skip/pumpkin/short-list 73946151 not compared
skip/pumpkin/string-list 222903052 not compared

write

Benchmark PR Change
write/nanonbt-borrow-signed/byte-array 16809 🔴 0.0%
write/nanonbt-borrow-signed/int-array 40269 🔴 0.0%
write/nanonbt-borrow-signed/long-array 71519 🔴 0.0%
write/nanonbt-borrow-signed/short-list 25059 🔴 0.0%
write/nanonbt-borrow/byte-array 16809 🔴 0.0%
write/nanonbt-borrow/chunk 92996 🟢 -14.9%
write/nanonbt-borrow/int-array 40269 🔴 0.0%
write/nanonbt-borrow/long-array 71519 🔴 0.0%
write/nanonbt-borrow/player 214904 🟢 -3.5%
write/nanonbt-borrow/short-list 25059 🔴 0.0%
write/nanonbt-borrow/small 13885 🟢 -0.9%
write/nanonbt-derive-signed/byte-array 16584 🔴 0.0%
write/nanonbt-derive-signed/int-array 1799951 🔴 +11.6%
write/nanonbt-derive-signed/long-array 3823595 🔴 +21.3%
write/nanonbt-derive-signed/short-list 1132522 🔴 +30.1%
write/nanonbt-derive/byte-array 13183 🔴 0.0%
write/nanonbt-derive/chunk 82104 🟢 -13.4%
write/nanonbt-derive/int-array 1766385 🔴 +11.9%
write/nanonbt-derive/long-array 3758781 🔴 +21.8%
write/nanonbt-derive/long-names 13178 🔴 0.0%
write/nanonbt-derive/player 191133 🟢 -3.9%
write/nanonbt-derive/short-list 1113838 🔴 +30.7%
write/nanonbt-derive/short-names 12863 🔴 0.0%
write/nanonbt-derive/small 5222 🟢 -2.3%
write/nanonbt-serde/chunk 501714 🟢 -0.2%
write/nanonbt-serde/long-names 129919 🔴 +0.7%
write/nanonbt-serde/player 673917 🟢 -0.1%
write/nanonbt-serde/short-names 127492 🔴 +0.2%
write/nanonbt-serde/small 56610 🟢 -0.2%
write/pumpkin/byte-array 27282 not compared
write/pumpkin/chunk 1350987 not compared
write/pumpkin/int-array 11547133 not compared
write/pumpkin/long-array 19078659 not compared
write/pumpkin/long-names 262461 not compared
write/pumpkin/player 1140527 not compared
write/pumpkin/short-list 211892484 not compared
write/pumpkin/short-names 187115 not compared
write/pumpkin/small 76721 not compared

iai-callgrind counts instructions under valgrind, so the same code counts the same instructions on every machine and every run; wasmi fuel is exact the same way, and the comparison needs no noise threshold and no repeated passes.

… libc memcpy

pulp relies on #[inline(always)] on the wrappers around its intrinsics; with plain
#[inline] the dispatch was not sunk into the hot loops and the rewrite lost most
of what the wide-based code had.

- mark the nanonbt and nanocesu8 dispatch helpers #[inline(always)] (and allow
  clippy::inline_always where that applies)
- fuse the memcpy in decode_be: copy 8-byte chunks that are already 4-aligned
  directly in the reversal loop, keeping the general fallback
- make the fallback copy on non-wasm targets a 64-byte read_unaligned /
  write_unaligned loop: for these mid-sized copies glibc's memcpy lands on
  rep movsb, which valgrind counts as thousands of instructions
- keep copy_nonoverlapping on wasm, where the std memcpy lowers to bulk
  memory.copy and beats byte-wise block copies
- test decode_be at every alignment and length 0..20
The compare jobs built both sides without --features simd, so every change the
pulp rewrite makes sat behind #[cfg(feature = "simd")] and CI reported identical
counts on both sides.  Build the native compare runs with simd enabled.

Do the same on wasm and execute real v128 code: add simd to WASM_FEATURES and
pass -C target-feature=+simd128 to the module builds only (the host build that
runs the bench needs no wasm SIMD).  wasmi now runs the module with its simd
feature, otherwise it refuses to load the SIMD opcodes at runtime.
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