1. 22
  1. 3

    This is a great summary, but it feels wrong that it completely glanced over dealing with destructors and shared resources. Sure, arenas are great and you can do this in a trivial way for pure-compute loads. It’s magic for parsers or per-frame info. But as soon as something holds a lock or opens a connection, you need to keep track of the objects somehow and potentially need to run destruction in order. The bump/reset pointer solution has some important limitations.

    1. 1

      Locks and connections feel like a good thing to stack allocate and handle the teardown nearby?

      int conn = accept(...);
      handle_socket(conn);
      close(conn);
      

      When would you use malloc here?

      1. 1

        The problem arises when a heap-allocated “object” owns such a resource, e.g. ‘conn’ is a field of a heap-allocated struct and released when the struct is freed. With an arena allocator, the resource isn’t released until the entire arena is freed. (If the allocator even bothers to run destructors / finalizers, which it often doesn’t.)

        I imagine what you’d do here is track that struct’s lifetime separately, and discover when it’s no longer needed and explicitly call a finalized to close the resource. Which is sort of a higher-level allocator, but at least you only need it for a small subset of heap blocks.

        1. 1

          Depends what handle_socket does and what’s the style of programming here. I mean, is this a thread? A green thread? What resources are related to this connection? How do you rate-limit? Is there a buffer between this connection and another? We don’t know any of that from this sample.

      2. 2

        I really enjoy using FixedBufferAllocator and ArenaAllocator in the Zig standard library.

        Those are often enough for the programs I write, along with the occasional heap allocation/resource aqcuisition with a corresponding defer cleanup; below.

        1. 1

          I’ve just read half of the article but it seems that the idea is similar to Jai programming langauge’s allocator system (linear allocation with a batch deallocation). Jai has a great howto explaining the author’s complaint of past memory management systems which unfortunately you can only read by being a secret beta user:)

          1. 1

            This was a really helpful post for me. I’m not used to working without a GC. Working with arenas though feels like something I could handle.

            1. 2

              Working with automatic ref-counting — Swift, Obj-C, C++ shared_ptr, Nim, etc. — also feels quite GC-like. Mostly you just need to consider the possibility of ref cycles causing leaks.