See #show and tell > roc on a unikernel (venting about LLM policies) for a little more context, but the executive summary is that zig 0.17 has a double-allocation bug that can plausibly bloat Roc programs.
Here's a tiny Roc app:
app [make] { pf: platform "./platform/main.roc" }
make : U64 -> List(U8)
make = |n| {
small = List.repeat(1, 100)
big = List.repeat(2, n)
big.concat(small)
}
The host's roc_alloc allocates from an ArenaAllocator, and I log what the arena asks of its own allocator. For make(1_000_000), Roc asks for 3,000,164 bytes in all:
stock Zig 0.17.0: arena node grows 1,500,120 -> 5,000,296; arena holds 5,000,272
patched 0.17.0: arena node grows 1,500,120 -> 3,500,152; arena holds 3,500,128
https://github.com/showell/patched-zig-compiler/commit/b2d40f4eff542f5a19c88107cb05b1b5872e57a4 is the fix. I'm not submitting upstream to zig for reasons that I mention on the other topic.
platform ""
requires {
make : U64 -> List(U8)
}
exposes []
packages {}
provides { "roc_make": make_for_host }
targets: {
x64musl: {
inputs: [app],
output: Archive,
},
}
make_for_host : U64 -> List(U8)
make_for_host = make
Isn't it related somehow to hugepages?
Or maybe allocating a bit more upfront, to reduce fragmentation and speed up subsequent allocations?
It's literally double allocating. Zig does allocate extra bytes optimistically, but the double allocation isn't intentional here. I saw the symptoms of it in a real-world program that's too big to post here.
https://github.com/showell/patched-zig-compiler/commit/502e0e447597f0b3e73c354f816a8abb1083c19f has more details.
(deleted message sent to wrong topic)
Last updated: Nov 04 2026 at 18:54 UTC