Skip to content Skip to footer
Cheating the Reaper in Go by ingve

Cheating the Reaper in Go by ingve

8 Comments

  • Post Author
    silisili
    Posted April 22, 2025 at 12:27 am

    I've been doing some performance tuning in Go lately to really squeak performance, and ended up with a very similar arena design except using byte slices for buf and chunks instead of unsafe pointers. I think I tried that too and it wasn't any faster and a whole lot uglier, but I'll have to double check before saying that with 100% confidence.

    A couple other easy wins –

    if you start with a small slice and find some payloads append large amounts, write your own append that preemptively is more aggressive in cap bumping before calling the builtin append.

    unsafe.String is rather new and great for passing strings out of byte slices without allocating. Just read the warnings carefully and understand what you're doing.

  • Post Author
    mholt
    Posted April 22, 2025 at 12:39 am

    Off topic, but I love the minimap on the side — for pages where I might be jumping around the content (long, technical articles, to refer back to something I read earlier but forgot) — how can I get that on my site? Way cool.

  • Post Author
    kristianp
    Posted April 22, 2025 at 1:52 am

    Just a quick meta note. This article is really lengthy, I don't have time to read this level of detail for the background. For example the "Mark and Sweep" section takes up more than 4 pages on my laptop screen. That section starts more than 5 pages into the article. Is this the result of having AI help to write sections, and as a result making it too comprehensive? It's easy to generate content, but the editing decisions to keep the important parts haven't been made. I just want to know the part about the Arena allocator, I don't need a tutorial on garbage collection as well.

  • Post Author
    foundry27
    Posted April 22, 2025 at 2:20 am

    tl;dr for anyone who may be put off by the article length:

    OP built an arena allocator in Go using unsafe to speed allocator operations up, especially for cases when you're allocating a bunch of stuff that you know lives and dies together. The main issue they ran into is that Go's GC needs to know the layout of your data (specifically, where pointers are) to work correctly, and if you just allocate raw bytes with unsafe.Pointer, the GC might mistakenly free things pointed to from your arena because it can't see those pointers properly. But to make it work even with pointers (as long as they point to other stuff in the same arena), you keep the whole arena alive if any part of it is still referenced. That means (1) keeping a slice (chunks) pointing to all the big memory blocks the arena got from the system, and (2) using reflect.StructOf to create new types for these blocks that include an extra pointer field at the end (pointing back to the Arena). So if the GC finds any pointer into a chunk, it’ll also find the back-pointer, therefore mark the arena as alive, and therefore keep the chunks slice alive. Then they get into a bunch of really interesting optimizations to remove various internal checks and and write barriers using funky techniques you might not've seen before

  • Post Author
    mkhattab
    Posted April 22, 2025 at 2:57 am

    > Go prioritizes not breaking the ecosystem; this allows to assume that Hyrum’s Law will protect certain observable behaviors of the runtime, from which we may infer what can or cannot break easily.

    If this assertion is correct, then effectively Go as a language is an evolutionary dead end. Not sure if I would Go fascinating in this case.

  • Post Author
    curtisszmania
    Posted April 22, 2025 at 3:09 am

    [dead]

  • Post Author
    fmstephe
    Posted April 22, 2025 at 3:48 am

    This article is a fun read.

    If you enjoyed this, or if you need more control over some memory allocations in Go, please have a look at this package I wrote. I would love to have some feedback or have someone else use it.

    https://github.com/fmstephe/memorymanager

    It bypasses the GC altogether by allocating its own memory separately from the runtime. It also disallows pointer types in allocations, but replaces them with a Reference[T] type, which offers the same functionality. Freeing memory is manual though – so you can't rely on anything being garbage collected.

    These custom allocators in Go tend to be arena's intended to support groups of allocations which live and die together. But the offheap package was intended to build large long-lived datastructures with zero garbage collection cost. Things like large in-memory caches or databases.

  • Post Author
    0xCafeBabee
    Posted April 22, 2025 at 7:26 am

    Interesting stuff! For folks building off-heap or arena-style allocators in Go—how do you usually test or benchmark memory safety and GC interactions in practice?

Leave a comment

In the Shadows of Innovation”

© 2025 HackTech.info. All Rights Reserved.

Sign Up to Our Newsletter

Be the first to know the latest updates

Whoops, you're not connected to Mailchimp. You need to enter a valid Mailchimp API key.