Skip to content

Experimental wasm memory.discard support - #1037

Draft
guybedford wants to merge 6 commits into
mainfrom
memory-discard
Draft

Experimental wasm memory.discard support#1037
guybedford wants to merge 6 commits into
mainfrom
memory-discard

Conversation

@guybedford

@guybedford guybedford commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

This adds experimental support for the WebAssembly memory-control proposal's memory.discard instruction, allowing Rust workers on workerd (behind the experimental wasm_memory_discard compatibility flag) to return freed memory pages to the operating system.

Wasm linear memory never shrinks, so today a worker's RSS is a high-water mark: memory freed by the allocator is never returned to the system. memory.discard semantically zeroes a page range while allowing the host to release the physical pages (madvise(MADV_DONTNEED)), making free almost as good as a fresh memory.

The full toolchain has landed upstream:

  • workerd — cloudflare/workerd#6999, behind the experimental wasm_memory_discard compatibility flag. The physical release is advisory: workerd may rate limit the page-table work by declining a release, in which case the range is zeroed instead — zero-readback is the only semantic guarantee, resident-memory reduction is best-effort
  • walrus — memory.discard instruction support landed in 0.26.5
  • wasm-bindgen#5287--experimental-memory-discard replaces an env.__wbindgen_memory_discard function import with a generated local function containing the memory.discard instruction
  • jemallocator-discard — jemalloc 5.3 built for wasm32-unknown-unknown (64KiB pages, single-threaded), with its madvise shim forwarding MADV_DONTNEED to the __wbindgen_memory_discard import. Page release uses jemalloc's standard decay: freed pages are reused freely within the decay window (default 10s) and released once idle past it, batching adjacent freed regions into few, large discards

This PR then adds:

  • WASM_BINDGEN_ARGS env passthrough in worker-build, used to pass --experimental-memory-discard to the wasm-bindgen CLI
  • worker-build glue advancing jemalloc's decay clock as each event settles (wasm has no clock; time is host-pushed via jemallocator-discard's __jemallocator_decay_tick export, frozen during requests so decay only progresses at event boundaries)
  • examples/memory-discard — a worker using jemalloc as the global allocator, with usage docs, a standard wrangler config, a /churn?mb=N endpoint that allocates, touches and frees N MB, plus a bench script measuring workerd RSS across the churn workload

Bench results across a 5×64MB churn workload:

variant RSS baseline RSS peak RSS after churn retained
jemalloc + memory.discard 81MB 146MB 85MB +4MB
jemalloc + memory.fill (zeroing, no release) 89MB 151MB 151MB +62MB
dlmalloc (status quo) 84MB 147MB 147MB +63MB

memory.discard returns essentially the entire churned working set to the OS; both baselines retain it in full. The memory.fill control was byte-for-byte identical except for the single instruction in the trampoline body, isolating the effect of the page release itself.

Caveats: linear memory itself never shrinks (84MB here), so address-space-derived limits are unaffected — this is purely a resident-memory win; jemalloc's retained-extent growth over-reserves by ~1.25× which can be capped via arena.<i>.retain_grow_limit if needed; binaryen has no memory-control support yet so wasm-opt is disabled for the example.

@guybedford
guybedford marked this pull request as ready for review August 18, 2026 02:49
@guybedford
guybedford force-pushed the memory-discard branch 2 times, most recently from fc9cc19 to 1381f3e Compare August 18, 2026 15:28
@codspeed-hq

codspeed-hq Bot commented Aug 18, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

✅ 2 untouched benchmarks


Comparing memory-discard (12929f3) with main (5f2d6c9)

Open in CodSpeed

@guybedford guybedford changed the title memory.discard allocator experiment Experimental wasm memory.discard support Aug 18, 2026
@guybedford
guybedford marked this pull request as draft August 18, 2026 21:34
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