Experimental wasm memory.discard support - #1037
Draft
guybedford wants to merge 6 commits into
Draft
Conversation
guybedford
force-pushed
the
memory-discard
branch
from
August 18, 2026 02:48
4d2efe9 to
6fb656e
Compare
guybedford
marked this pull request as ready for review
August 18, 2026 02:49
guybedford
force-pushed
the
memory-discard
branch
2 times, most recently
from
August 18, 2026 15:28
fc9cc19 to
1381f3e
Compare
Merging this PR will not alter performance
|
guybedford
force-pushed
the
memory-discard
branch
from
August 18, 2026 15:45
1381f3e to
12929f3
Compare
guybedford
force-pushed
the
memory-discard
branch
from
August 18, 2026 19:47
78033ec to
5f2ec47
Compare
guybedford
marked this pull request as draft
August 18, 2026 21:34
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.
This adds experimental support for the WebAssembly memory-control proposal's
memory.discardinstruction, allowing Rust workers on workerd (behind the experimentalwasm_memory_discardcompatibility 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.discardsemantically 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:
wasm_memory_discardcompatibility 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-effortmemory.discardinstruction support landed in 0.26.5--experimental-memory-discardreplaces anenv.__wbindgen_memory_discardfunction import with a generated local function containing thememory.discardinstructionmadviseshim forwardingMADV_DONTNEEDto the__wbindgen_memory_discardimport. 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 discardsThis PR then adds:
WASM_BINDGEN_ARGSenv passthrough in worker-build, used to pass--experimental-memory-discardto the wasm-bindgen CLIjemallocator-discard's__jemallocator_decay_tickexport, 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=Nendpoint that allocates, touches and frees N MB, plus a bench script measuring workerd RSS across the churn workloadBench results across a 5×64MB churn workload:
memory.discardmemory.fill(zeroing, no release)memory.discardreturns essentially the entire churned working set to the OS; both baselines retain it in full. Thememory.fillcontrol 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_limitif needed; binaryen has no memory-control support yet sowasm-optis disabled for the example.