igoriakovlev opened issue #13756:
Test Case
Steps to Reproduce
Run the following command:
wasmtime -W gc,exceptions,function-references --dir=/ $PWD/kotlin-wasm-benchmarks-wasmWasiBenchmark.wasm STUB $PWD/config.conf StringBenchmark microBenchmarks.StringBenchmark.stringConcatNullableExpected Results
Benchmarks are running.
Actual Results
GC heap out of memory: no capacity for allocation of 96 byteswhen-C collector=copying
wasm trap: allocation size too largewhen-C collector=nullVersions and Environment
Wasmtime version or commit: 46.0.1
Operating system: MacOS 26.5.1
Architecture: Apple Silicon
Extra Info
With
-C collector=drcbenchmarks works good. Seems since 46.0.1 the default GC was changed from drc to copying so tests are now fails.
igoriakovlev added the bug label to Issue #13756.
alexcrichton added the wasm-proposal:gc label to Issue #13756.
alexcrichton assigned fitzgen to issue #13756.
fitzgen commented on issue #13756:
Hm I'm having trouble reproducing. With both the copying and DRC collectors I get an uncaught exception from the Wasm program, with no diagnostics printed, sometime after the GC heap grows to 1MiB:
2026-06-29T21:46:14.381956Z TRACE wasmtime::runtime::store::gc: -> grew GC heap by 0x80000 bytes: new size is 0x100000 bytes Error: failed to run main module `kotlin-wasm-benchmarks-wasmWasiBenchmark.wasm` Caused by: 0: failed to invoke command default 1: error while executing at wasm backtrace: 0: 0xecd4a - <org.jetbrains.benchmarks:kotlin-wasm-benchmarks_wasmWasiBenchmark>!kotlinx.benchmark.generated.mainWrapper 2: thrown Wasm exception
igoriakovlev commented on issue #13756:
Hi. Looks like something wrong with the IO and preopens. I have inlined all IO so you can run this without config and with simple command:
wasmtime -W gc,exceptions,function-references ./kotlin-wasm-benchmarks-wasmWasiBenchmark.wasm
fitzgen commented on issue #13756:
@igoriakovlev thanks! Will take a look again soon
fitzgen closed issue #13756:
Test Case
Steps to Reproduce
Run the following command:
wasmtime -W gc,exceptions,function-references --dir=/ $PWD/kotlin-wasm-benchmarks-wasmWasiBenchmark.wasm STUB $PWD/config.conf StringBenchmark microBenchmarks.StringBenchmark.stringConcatNullableExpected Results
Benchmarks are running.
Actual Results
GC heap out of memory: no capacity for allocation of 96 byteswhen-C collector=copying
wasm trap: allocation size too largewhen-C collector=nullVersions and Environment
Wasmtime version or commit: 46.0.1
Operating system: MacOS 26.5.1
Architecture: Apple Silicon
Extra Info
With
-C collector=drcbenchmarks works good. Seems since 46.0.1 the default GC was changed from drc to copying so tests are now fails.
fitzgen commented on issue #13756:
Unfortunately, this is the copying collector behaving as expected. It divides the GC heap into two semi-spaces, so its maximum heap utilization is 50%. The GC heap is a Wasm linear memory, which means its maximum size is 4GiB, which means that the copying collector supports a 2GiB maximum live set (well, actually just under 2GiB). Looking at the GC logs, Wasmtime grows the GC heap to its maximum capacity, but the benchmarks fill up all of that space and on the next allocation attempt this triggers the GC heap out of memory trap:
2026-07-01T00:38:46.716561Z TRACE wasmtime::runtime::store::gc: Attempting to grow the GC heap by at least 0x60 bytes 2026-07-01T00:38:46.716570Z TRACE wasmtime::runtime::store::gc: ============ Begin GC =========== GC heap capacity = 0x100000000 bytes last post-GC live-set size = 0x7fffffd0 bytes GC heap utilization = 50.00% ... 2026-07-01T00:39:52.846487Z TRACE wasmtime::runtime::store::gc: ============ End GC =========== GC heap capacity = 0x100000000 bytes post-GC live-set size = 0x7fffffd0 bytes GC heap utilization = 50.00% Error: failed to run main module `/Users/n.fitzgerald/Downloads/kotlin-wasm-benchmarks-wasmWasiBenchmark.wasm` Caused by: 0: failed to invoke command default ... 2: GC heap out of memory: no capacity for allocation of 96 bytesSo in order to run these benchmarks with Wasmtime's copying collector, you'll have to adjust the program so that their working set size is below 2GiB (and ideally fairly comfortably below that, probably around 1GiB is safe, as any collector's performance will become pathological as you approach its maximum heap capacity).
The DRC collector does not divide the heap into two semi-spaces, so it can utilize the full 4GiB heap, and this is why the program completes under the DRC collector.
bashor commented on issue #13756:
@fitzgen
Is 4GiB a maximum possible size for the GC heap?
Does the null collector also fail for the same reason (no free memory to allocate)? Even so, wasmtime returns different error codes for these cases (1 and 134), is it expected?
bashor commented on issue #13756:
I've tried
gc-heap-reservationandgc-heap-reservation-for-growthto increase and decrease the GC heap size, but they seem to have no effect.
fitzgen commented on issue #13756:
@bashor
Is 4GiB a maximum possible size for the GC heap?
Correct. The GC heap is implemented with a 32-bit linear memory so that we can reuse Wasmtime's existing sandboxing mechanisms for it.
Does the null collector also fail for the same reason (no free memory to allocate)?
Presumably (I haven't actually run it) the null collector fails because even though the maximum live-set of the benchmark is within 4GiB, it allocates more than 4GiB of GC objects and relies on the collector to actually reclaim garbage, which the null collector does not do.
Even so, wasmtime returns different error codes for these cases (1 and 134), is it expected?
They should probably return the same error / exit code. If you're not seeing that, then probably what is happening is one is reporting
GcHeapOutOfMemory(no more space in the GC heap, try dropping GC references, collecting, and then trying again) and the otherAllocationTooLarge(the allocation will never fit in the GC heap, regardless of how many GC references you drop and collections you perform). Its plausible that we should just removeAllocationTooLargeand only haveGcHeapOutOfMemoryor something like that.I've tried
gc-heap-reservationandgc-heap-reservation-for-growthto increase and decrease the GC heap size, but they seem to have no effect.These knobs will tweak the amount of memory reserved for the initial GC heap allocation and how much extra space for future GC heap growth we reserve on every GC heap reallocation respectively. Neither will have semantically visible impacts on the program or the maximum GC heap capacity, just performance implications when growing up towards the maximum GC heap capacity.
bashor commented on issue #13756:
@fitzgen Thanks for the clarification!
fitzgen commented on issue #13756:
@bashor no problem. Btw, you might be interested to know that we added a Kotlin benchmark to Sightglass (our benchmarking suite and tooling for Wasmtime and Cranelift): https://github.com/bytecodealliance/sightglass/tree/main/benchmarks/kotlin-richards
Last updated: Jul 29 2026 at 05:03 UTC