Stream: git-wasmtime

Topic: wasmtime / issue #13756 Kotlin benchmarks fails with memo...


view this post on Zulip Wasmtime GitHub notifications bot (Jun 29 2026 at 15:54):

igoriakovlev opened issue #13756:

Test Case

issue.zip

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.stringConcatNullable

Expected Results

Benchmarks are running.

Actual Results

GC heap out of memory: no capacity for allocation of 96 bytes when -C collector=copying
wasm trap: allocation size too large when -C collector=null

Versions and Environment

Wasmtime version or commit: 46.0.1

Operating system: MacOS 26.5.1

Architecture: Apple Silicon

Extra Info

With -C collector=drc benchmarks works good. Seems since 46.0.1 the default GC was changed from drc to copying so tests are now fails.

view this post on Zulip Wasmtime GitHub notifications bot (Jun 29 2026 at 15:54):

igoriakovlev added the bug label to Issue #13756.

view this post on Zulip Wasmtime GitHub notifications bot (Jun 29 2026 at 15:59):

alexcrichton added the wasm-proposal:gc label to Issue #13756.

view this post on Zulip Wasmtime GitHub notifications bot (Jun 29 2026 at 15:59):

alexcrichton assigned fitzgen to issue #13756.

view this post on Zulip Wasmtime GitHub notifications bot (Jun 29 2026 at 21:54):

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

view this post on Zulip Wasmtime GitHub notifications bot (Jun 30 2026 at 11:06):

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

kotlin-wasm-benchmarks-wasmWasiBenchmark.wasm.zip

view this post on Zulip Wasmtime GitHub notifications bot (Jun 30 2026 at 17:23):

fitzgen commented on issue #13756:

@igoriakovlev thanks! Will take a look again soon

view this post on Zulip Wasmtime GitHub notifications bot (Jul 01 2026 at 00:56):

fitzgen closed issue #13756:

Test Case

issue.zip

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.stringConcatNullable

Expected Results

Benchmarks are running.

Actual Results

GC heap out of memory: no capacity for allocation of 96 bytes when -C collector=copying
wasm trap: allocation size too large when -C collector=null

Versions and Environment

Wasmtime version or commit: 46.0.1

Operating system: MacOS 26.5.1

Architecture: Apple Silicon

Extra Info

With -C collector=drc benchmarks works good. Seems since 46.0.1 the default GC was changed from drc to copying so tests are now fails.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 01 2026 at 00:56):

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 bytes

So 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.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 01 2026 at 23:13):

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?

view this post on Zulip Wasmtime GitHub notifications bot (Jul 01 2026 at 23:19):

bashor commented on issue #13756:

I've tried gc-heap-reservation and gc-heap-reservation-for-growth to increase and decrease the GC heap size, but they seem to have no effect.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 01 2026 at 23:38):

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 other AllocationTooLarge (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 remove AllocationTooLarge and only have GcHeapOutOfMemory or something like that.

I've tried gc-heap-reservation and gc-heap-reservation-for-growth to 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.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 02 2026 at 21:42):

bashor commented on issue #13756:

@fitzgen Thanks for the clarification!

view this post on Zulip Wasmtime GitHub notifications bot (Jul 03 2026 at 03:00):

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