Last week I met with Wojciech Mazur (the maintainer of Scala Native), we tried a couple changes in SN, which increased the amount of allocations I'm able to do with GC on, without breaking the game.
One important note was that we should preallocate a heap ahead of time, and not allow it to grow: because we're only able to use malloc and not mmap, and the heap segments are supposed to be located next to each other in memory (at least from the program's POV), heap allocation is just asking for trouble and reading some arbitrary memory instead of what was allocated.
So, we're now allocating around 10MB if my memory serves me. This worked for 20 rounds of 128k allocations or so.
Fast forward to today - I saw that Wojciech got a couple GC-related changes to the main branch, including fix: Try to stablize GC by WojciechMazur · Pull Request #3767 · scala-native/scala-native · GitHub, I tried them out and... it seems to just... work like a charm?
I can do 256k rounds of allocations, as often as I want (one round takes several seconds because I assume the hardware isn't that fast), and I see only ~87 blocks (out of the 283 allocated) are getting used. 512k allocations hang the game loop for over 10 seconds so the game crashes - but I don't think I'd need that many anyways
Going back to lower numbers like 16k allocations seems to clear up all the blocks. At this point I think it's safe to say that the GC is working much much better than before.
I would love to get stack traces to work (with libunwind), but given the time constraints (T minus 34 days for the conference talk), I think the bigger priority is the actual game code. Perhaps I'll try the bindings once more.