> The real reason was the “Infectious API” problem. To get performance benefits, you can’t just create an arena locally; you have to pass it down the call stack so functions can allocate inside it. This forces a rewrite of function signatures.
Sorry, but it doesn't seem that difficult (famous last words). Add a new implicit parameter to all objects just like "this" called "thisArena". When a call to any allocation is made, pass "thisArena" implicitly, unless something else passed explicitly.
That way the arena is viral all the way down and you can create sub-arenas. It also does not require actually passing the arena as parameter.
You don't even need to rewrite any new code, just recompile it.
That design introduces two kinds of overhead at runtime:
- You need a pointer to the allocator (presumably you’d want to leave room for types beyond arenas). That’s 8 bytes of extra size on every object.
- You need to dynamically dispatch on this pointer for every allocation. Dynamic dispatch is a lot cheaper than it used to be on modern architectures, but it’s a barrier for basic inlining, which is a big deal when alloc() for an arena is otherwise just a pointer bump.