4 ms·
Yeah, arena allocators are a great tool, but they are not a magic bullet either. Also the author's condescension about automatic memory management is... tellin
by Diggsey 4y ago
Yeah, arena allocators are a great tool, but they are not a magic bullet either.
Also the author's condescension about automatic memory management is... telling. Remembering to call "free" is only one small part of why tools like RAII are good, and arena allocators do not help with the other parts.
The overall goal is to be able to write correct, reliable, performant software. Arena allocators help prevent missed or double frees, but they don't help with the other memory safety issues. For example, sometimes objects in different arenas need to reference each other and C does not help prevent you from accessing those references after one of the arenas has been freed.
On top of that there are general issues with arena allocators:
1. They can be inefficient for resizable collections where you don't know the total length in advance. The multiple re-allocations results in a lot of wasted space in the arena.
2. In C, it's implicit which objects should belong to which arena.
3. It's not composable. A library doesn't necessarily know which objects should use which arena, or may not even support arena allocation at all.
4. There are other resources than just memory. There's a reason it's called RAII and not MAII - because it allows you to clean up all kinds of resources (eg. file handles) when an arena allocator doesn't typically support any kind of destructor.
5. It requires more thought to structure your program in this way. For some programs that may be effort well spent, but a lot of programs are not bound by allocation performance, and for those programs not thinking about allocation at all leaves more time for thinking about correctness in other aspects.
6. Languages which do automatic memory management can still support arenas, and may offer additional benefits when they do (eg. Rust's explicit lifetimes can tie an object to the arena it came from).
7. The stack and heap are global resources that most code can simply assume exist, and use with no extra ceremony. When you have arenas in play, these need to be passed as additional arguments. Adding a new allocation to a function can require sweeping changes to add a new arena parameter to every function above it in the call stack.
- jeltz 4y agoI generally agree with what you wrote but have some corections based on having worked with arena allocators. 4. Nothing prevents arena allocators to track other resources than memory. 7. This is not a big problem in practice from my experience. You can just do like Zig and always pass an allocator or you can use global/thread local variables like PostgreSQL. But I also would like to add my biggest issue with arena allocators: they do nothing against use after free.
- hinkley 4y ago> 3. It's not composable. A library doesn't necessarily know which objects should use which arena, or may not even support arena allocation at all. > 6. Languages which do automatic memory management can still support arenas, and may offer additional benefits when they do (eg. Rust's explicit lifetimes can tie an object to the arena it came from). Languages with automatic memory management don't expose the arenas as an implementation detail, and so they are free to work out how to compose them, and when to change their minds. Java has had copying collectors practically from the beginning, and that ability to rewrite pointers after the fact affords you the ability to work with heuristics that have known failure modes, where any mistake becomes a use-after-free bug. Moving an object out of a volatile arena is just an inconvenience. So it evolved from generational collectors, to thread local arenas, to thread local arenas where some objects that are likely to survive are never allocated into the arena but 'pre-tenured'. This process really hit its stride with the introduction of escape analysis, which is a logical ancestor of today's borrow checker. With escape analysis you know for certain some objects never escape, in which case you can even inline simple objects (eg, register allocation). And if an arena has an escape probability of 0, there's less guard logic to deal with, and there is some short circuiting one can do when considering the root set for Mark and Sweep.