fitzgen opened issue #13231:
My rough assumption as well is that long-term we'll want nurseries as well, right? If that's the case would it make sense to document that in an issue as an open future work item?
Not totally clear to me right now. A nursery probably isn't worth it for our typical short-running programs, since we can mostly just avoid collecting in those cases, and would only slow down wasm execution via the write barriers it would require. (Also, our amortized GC heap growth algorithm effectively means we have N nursery collections on the way to the full heap size, if you squint hard.)
But someone with long-running wasm instance use cases may indeed want a nursery. But then we also wouldn't want to force a nursery on the short-running use cases that don't need it.
Seems like the kind of bridge we can cross when we get to it. I wouldn't go so far as to say that we should expect it to happen with enough certainty that a tracking issue is required at this time.
_Originally posted by @fitzgen in https://github.com/bytecodealliance/wasmtime/issues/13107#issuecomment-4254865035_
Also, regarding my above comment, we could potentially introduce another collector that has a nursery and is tuned for longer-running Wasm instances, while keeping the copying collector as it is today without a nursery.
Or somehow make it a cargo feature or something, but that seems pretty hairy.
In addition to the above discussion, there is the question of how to implement the nursery, and in particular its remembered set, with O(1)-sized host data structures outside of the GC heap's memory.
The remembered set is the set of GC edges from the tenured heap into the nursery.
A typical approach might be something like a chunk-list where we bump into each chunk until we run out of capacity and then allocate another chunk, and chunks form a linked list together. The problem is that this means that
GcStore::write_gc_refmight need to allocate, which might need to grow the GC heap or trigger a collection, so it would need to become async and fallible, which means it needs to keep GC objects in a valid state for retry after GC, which is just a huge can of worms given that the remembered set is required to perform GC correctly.We could alternatively have an intrusive linked list in tenured objects' headers, and inclusion in this list means that one of your edges is in the remembered set. This is a big overapproximation of the remembered set, and if a very large array has one edge in the remembered set, then we will need to scan the whole array when collecting the nursery. But it does give use the O(1)-sized host data structures property.
- We could potentially alleviate the large-array issue by doing a variant of card marking, where we have a bitmap in the array with a bit for every N elements and we set an element's associated bit when it is inserted into the remembered set. This caps wasted tracing to
N - 1at most but imposes size overhead and makes barriers more expensive.Some kind of hybrid set up where we use a chunk-list when possible but fall back to the intrusive linked list of tenured objects when allocating a new chunk fails and would require GC or heap growth? Does the fast thing when it can, falls back to the slower thing when it can't to avoid the fallibility/async/gc in the middle of a barrier question. Downsides are additional complexity, we would always pay for the size of the linked-list link in object headers, even when the remembered set fully fits in the chunk-list, and more-expensive barriers.
Certainly there are other ideas to explore here. I mostly just wanted to write this stuff down and get it out of my head while it is fresh. I don't actually expect us to make any moves here anytime soon.
fitzgen added the wasm-proposal:gc label to Issue #13231.
Last updated: May 03 2026 at 22:13 UTC