Repository navigation
Commit a361d8f
authored
perf: keep shared-memory locking out of line (#72)
Since the threads proposal landed, `with_memory!` takes a shared
memory's lock inline and holds the guard until the access ends, and this
actually dropped tinywasm's leaderboard placement in my WasmBench app on
multiple devices. With the inline lock, load and store handler contain
the `lock` and `unlock` calls, even though `core::hint::cold_path()`
marks that branch cold. To keep values alive across those calls, each
handler saves extra callee-saved registers on every access, whether or
not the memory is shared.
This runs the shared-memory body in a `#[cold]`, `#[inline(never)]`
helper that takes the lock. (There is a `core::hint::cold_path()` in
there, but when I looked at the disassembled code for the Release build,
it didn't affect codegen and Rust docs verify that its not necessarily
meant to influence codegen.) The ordinary-memory path stays inline,
which is seemingly more common in the wild, but if you have some
specific workload you're optimizing for and need both paths to be
equally fast, I can go back to the drawing board.
Everything measured with XCode 27's PMU template, the same approach I
used for measuring and optimizing other projects (WAMR, wgpu-native,
femtovg, BabylonNative, xmrsplayer, etc) on this set of hardware.
On aarch64 (iPhone XS A12 codegen, `nightly-tail-calls`):
| handler | before | after |
|---|---|---|
| `I32Store` | 188 instructions, 5 saved register pairs, 17 calls | 137
instructions, 3 pairs, 8 calls |
| `I32Load` | 186 instructions, 5 pairs, 16 calls | 142 instructions, 3
pairs, 8 calls |
Three memory.copy / data-segment bodies used `?` inside the macro for a
unit result. They now return the `Result` and apply `?` outside the
macro, so a body means the same thing on both paths.
**iPhone 12 (A14) efficiency cores.** Per-call medians of the kernel's
retired-instruction and cycle counters, 5 interleaved runs of each
build:
| row | instructions | cycles |
|---|---:|---:|
| byte-hash loop over one memory | −3.6% | −4.2% |
| convolution 256×256 (scalar) | −5.7% | −3.3% |
| sieve (scalar) | −4.2% | −7.8% |
| crc32 64 KB (scalar) | −4.0% | −6.3% |
| xmrsplayer | −2.7% | −1.1% |
| graphql-validation (AS) | −3.4% | −2.7% |
| shared memory: plain load/store | −4.2% | −4.1% |
| shared memory: atomic RMW | −6.3% | −10.7% |
| ordinary memory: plain load/store | −5.8% | −4.4% |
| fib(30), no memory ops | −0.1% | −0.0% |
**Apple Watch Series 10.**Per-call medians of the kernel's
retired-instruction and cycle counters:
| row | instructions | cycles |
|---|---:|---:|
| byte-hash loop over one memory | −4.6% | −8.6% |
| convolution 256×256 (scalar) | −5.8% | −4.8% |
| sieve (scalar) | −4.2% | −8.3% |
| crc32 64 KB (scalar) | −4.0% | −6.2% |
| xmrsplayer | −2.9% | −3.6% |
| graphql-validation (AS) | −3.3% | −2.8% |
| fib(30), no memory ops | −0.2% | −0.0% |

The screenshot is one 1-second run. Full data: [tinywasm on the Apple
Watch Series
10](https://github.com/rebeckerspecialties/wasm-benchmark/blob/app-store-ui/docs/tinywasm-watch-2026-09-26.md).1 parent 693d590 commit a361d8f
3 files changed
Lines changed: 57 additions & 12 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1432 | 1432 | | |
1433 | 1433 | | |
1434 | 1434 | | |
1435 | | - | |
| 1435 | + | |
1436 | 1436 | | |
1437 | 1437 | | |
1438 | 1438 | | |
| |||
1484 | 1484 | | |
1485 | 1485 | | |
1486 | 1486 | | |
1487 | | - | |
| 1487 | + | |
1488 | 1488 | | |
1489 | 1489 | | |
1490 | 1490 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
| 38 | + | |
37 | 39 | | |
38 | 40 | | |
39 | 41 | | |
| |||
822 | 824 | | |
823 | 825 | | |
824 | 826 | | |
825 | | - | |
826 | | - | |
827 | | - | |
| 827 | + | |
| 828 | + | |
828 | 829 | | |
829 | 830 | | |
830 | 831 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
30 | 34 | | |
31 | | - | |
| 35 | + | |
32 | 36 | | |
33 | 37 | | |
34 | 38 | | |
35 | 39 | | |
36 | 40 | | |
37 | 41 | | |
38 | | - | |
39 | 42 | | |
40 | 43 | | |
41 | 44 | | |
| |||
52 | 55 | | |
53 | 56 | | |
54 | 57 | | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
55 | 85 | | |
56 | 86 | | |
57 | 87 | | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
58 | 102 | | |
59 | 103 | | |
60 | 104 | | |
| |||
120 | 164 | | |
121 | 165 | | |
122 | 166 | | |
123 | | - | |
124 | | - | |
| 167 | + | |
| 168 | + | |
125 | 169 | | |
126 | | - | |
127 | | - | |
| 170 | + | |
| 171 | + | |
128 | 172 | | |
129 | 173 | | |
130 | 174 | | |
| |||
0 commit comments