Making performant dynamic manual memory management in C feel almost like garbage collection.
A couple of questions:
1. People usually make a scratch arena locals to a thread using something like __declspec(thread). What if you're on a platform or project that can't use thread-local storage? I usually see people handle this by passing around a "thread context" Care to comment on that?
2. The push and pop operator on the current arena implementation aren't atomic, which mean they aren't thread-safe. How do you go about dealing with memory management for multithreading?
3. Do you think the idea of ArenaTemp can be made more abstract and applied to other kinds of allocators? For example, I may have a generic heap allocator that keeps a free list and allows for out-of-order alloc and free allocations. I can still create an ArenaTemp for this allocator by storing the free list in the ArenaTempBegin and restoring it in the ArenaTempEnd function. The same also goes for a pool allocator, for example. I can still store the current free list and reset it later.
Ah, I love this :D
Thanks for the article! Very inspiring.
I wonder what you think about pathological cases with the pool allocator, where memory gets tied up in the free list of one struct and becomes unavailable for other allocations.
For example, let's say that, through user error, the level editor for a game allocates and frees 200k entities (the user selected the entire level and copied it 100 times by accident, then pressed undo). Now a potentially large amount of memory gets leaked into the entity free list (and other associated free lists).
Perhaps this is a reason to use a malloc-style allocator, where freeing memory makes it available for other kinds of allocations?
Hi Ryan! Loved the article so much I just subscribed!
Is the Code Depot with the example locked? Would love to see how you use Arena Allocation in a small example.
Regarding the per-thread scratch arena system, can you have an additional per-thread int scratchCount that increases every time you call GetScratch and decreases every time you call ReleaseScratch? Then every time you need a new scratch arena, rather than searching, you can get it from the index after the int. This will also give the maximum number of unique scratches you need in any instance.
Fantastic post! Mind-expanding and elegant :-D.
I just have one question: how do we pull data out of the arena? And why not make arenas hash maps rather than contiguous blocks, so we can pull out the values by name, even though that would be a bit less efficient?
Good to see you introduce arenas. Your APIs that take `arena` as parameter remind me of Zig, are the concepts identical?