josefguenther opened PR #14714 from josefguenther:feat/memory-discard to bytecodealliance:main:
Closes #9572.
This adds
Memory::discard(store, start, count), the host API fitzgen sketched in #9572. It zeroes Wasm pages of a non-shared memory and gives them back to the OS where Wasmtime owns the mapping. Likegrowandsize, it counts in Wasm pages, so a range is always page-aligned. The memory's size and base pointer don't change, and the pages read as zeros if they are touched again. Linear memory can't shrink, so this lets an embedder whose guest allocator frees large spans return that memory instead of holding the guest's high-water mark until the instance is dropped.The separate
memory.discardproposal takes bytes and rounds them to whole pages; taking pages means nothing is rounded and is consistent with grow/size, so that's the approach I took.How it works:
- On Linux it calls
madvise(MADV_DONTNEED)on the pages. Other Unix platforms map fresh zeroed memory over them, and Windows decommits and recommits them.- If the memory was initialized from a copy-on-write image,
madviseon Linux would bring back the image's data instead of zeros. So that part gets fresh zeroed memory, and the slot drops the image at its next reset, as resets already do on other platforms. The next instance maps the image again.- Memories that Wasmtime doesn't map itself, such as a custom LinearMemory, are zeroed by writing. They read the same afterwards, but no memory is released.
- Pages out of bounds, or a memory with a custom page size, return an error. Shared memories aren't supported.
- The C API gets
wasmtime_memory_discardand the C++ APIMemory::discard, consistent with the rest.The tests cover each of these cases, including the Linux image case, and a C++ test covers the new binding. I ran the Rust tests on macOS and on x86_64 and aarch64 Linux, and the C API tests on macOS.
This is my first contribution to wasmtime and it's a larger one, so let me know if you have changes or concerns.
josefguenther requested fitzgen for a review on PR #14714.
josefguenther requested wasmtime-core-reviewers for a review on PR #14714.
github-actions[bot] added the label wasmtime:c-api on PR #14714.
github-actions[bot] added the label wasmtime:api on PR #14714.
:memo: fitzgen submitted PR review:
Thanks! Overall looks good to me, but I have a few comments/questions below.
:speech_balloon: fitzgen created PR review comment:
I realize this is a pre-existing comment, but it should end with "or restore the original mapping" as per
decommit_behaviorjust below.
:speech_balloon: fitzgen created PR review comment:
We should document that this method will trap when given out-of-bounds regions to discard, and that callers should have already done their own bounds checks.
:speech_balloon: fitzgen created PR review comment:
Isn't it the opposite? When we restore the original mapping we get the CoW image, not zeros.
:speech_balloon: fitzgen created PR review comment:
As just mentioned, we should match the proposed instruction and use bytes-rounded-to-pages rather than pages.
:speech_balloon: fitzgen created PR review comment:
Doc comment mentions
lenandoffsetbut the parameters arecountandstart.Also, I think we should match the proposed
memory.discardinstruction's parameters, which last time I looked was bytes that get rounded to page multiples of the memory's page size. I personally think the instruction should take pages instead of bytes, but that is a spec conversation to have, and not matching it in the wasmtime API would be even worse. We can always change this API if the instruction changes its operands.
:speech_balloon: fitzgen created PR review comment:
Why do we only need to reapply the pkey for the overlap and not for the anonymous ranges? Especially since the
DecommitBehavior::Zerobranch reapplies it to the whole range.
:speech_balloon: fitzgen created PR review comment:
This makes it sound like a guarantee, which it is not. If the platform does not support virtual memory, then we will just write the zeroes.
And this may not be what the embedder wants, so it may make sense to also expose a method for testing whether
wasmtime::Memory::discardwill write zeroes or use virtual memory so they can decide what to do in that case. This doesn't need to be part of this PR though, fine as a follow up PR or a new issue so we don't forget about it.
:speech_balloon: fitzgen created PR review comment:
It looks like we are not quite complete on the different kinds of overlaps:
- [ ] before
- [x] overlapping start
- [x] inside
- [x] overlapping end
- [ ] overlapping both the start and the end (i.e. containing the image)
- [x] after
:speech_balloon: fitzgen created PR review comment:
Also, we should test each of these both when dirty and when not dirty.
:speech_balloon: fitzgen created PR review comment:
Unless the memory creator's memory overwrites the default
RuntimeLinearMemory::discardimplementation, right? That seems like an important disctinction and that we should link to that method's docs from here.
:speech_balloon: fitzgen created PR review comment:
The last one is not an empty range?
Last updated: Oct 31 2026 at 23:03 UTC