Live data from Hacker News

Untangling Lifetimes: The Arena Allocator

rfleury.com

21–30 of 94 posts

Re: Untangling Lifetimes: The Arena Allocator

#22
post #3

Anyone read it all and can tldr any interesting insights?

It's a good technical explanation of how arena allocation (a useful and easily googleable memory management technique) works in practice, in C, along with: * A lot of arguing that all other ways of dealing with the problem (garbage collectors, RAII, etc) are misguided and make for worse programs. This is a lot more controversial than "arena allocation is useful" but I have some sympathy for it. He's not alone in thin…

If it seems like he is implying he came up with arena allocators himself, that is definitely not intended. I didn't read it like that though.

Re: Untangling Lifetimes: The Arena Allocator

#23
post #7

The author should take another look at RIIA. The first big difference is that it works with non-memory resources too, for example open/close for files. The second is that it makes heap allocated data feel a lot like stack allocated data, since the resources are ultimately owned by variables on the stack. With “move semantics” resources can be passed as arguments and returned by functions too, so the example of lifeti…

IMHO the problem with C++ style RIIA is that it's not just about calling cleanup code at the end of a scope (this would be fine, really), but the 'rat's tail' that's attached to RAII for dynamic memory management: you also need the compiler to be able to invoke user-provided code for 'copy' and 'move' operations (or better named: deep- and flat-copy), you need different reference types to define ownership details (e.g. unique vs shared) etc... this adds a lot of bells and whistles to the language which is only needed in special situations (such as tracking the individual lifetimes of tons of tiny heap objects, which usually isn't a good idea in the first place).

Re: Untangling Lifetimes: The Arena Allocator

#24
For me as non native speaker it is interesting choice of words with 'Untangling'. While arenas achieve the goal to simplify lifetime management by reducing number of different lifetimes they do it by effectively 'entangling' lifetimes. If arenas are reused they make UAF detection a problem that needs special care. Performance is usually great so it is used everywhere not only in gamedev.

Re: Untangling Lifetimes: The Arena Allocator

#27
post #4

Earlier quoted context omitted.

This came up before. TL;DR: If you use arena allocators everywhere then you won't have any memory errors! I think the idea is a really interesting one but it would be better if he didn't wrap it in typical "I don't make mistakes" hubris. I mean I guess at least this time he has some more reason than "because I'm not stupid" but I think he's still wrong. His technique probably reduces the chance of memory errors, but…

> I would say RAII and Rust's borrow checker are still superior but it's definitely true that they don't work well with arenas. Note that this will definitely improve in future versions of Rust. Local allocators are an unstable feature already, and can support arena allocation.

As a C programmer who uses memory arenas quite frequently can you expand on what you know about Rust’s current or future support for such a feature?

I’d like to start writing new projects in Rust and I’d like to continue to use this approach to memory management!

Re: Untangling Lifetimes: The Arena Allocator

#28
> In other words, you may treat the operating system as “the ultimate garbage collector”—freeing memory when it is unnecessary will simply waste both your and the user’s time, and lead to code complexity and bugs that would otherwise not exist. Unfortunately, many popular programming education resources teach that cleanup code is always necessary. This is false.

I disagree. One, I think the set of C code where both "allocates enough pointers that calling 'free' is too complicated" and "memory leaks are not a problem due to short runtime/low memory usage" is very small. Two, having a pattern where calling free is too complicated might indicate problems with the code: if your code makes it hard to manage lifecycles, I bet it makes several other things harder than they should be. Three, one should think what happens when that code is used in other places: writing proper lifecycle management at the beginning is easier than doing it when it's used as a library.

> This simplifies all codepaths in this system. The parsing code becomes simpler, because it does not have to have any cleanup code whatsoever. The calling code becomes simpler, because it does not have to manage the lifetime of the parsed tree independently. And finally, the allocator code itself remains nearly trivial, and lightning fast.

Again, disagree. The calling code becomes more complex because now you have to link the arena to the object it creates. It's very easy to make the mistake of passing the object without the associated arena, then releasing the arena, and boom the object is now garbage. And, as I saw in another comment, cleanup might involve more things than just "freeing memory", so you might end up iterating all the structures nevertheless. On the other hand, with RAII and smart pointers (or GC, or refcounting), you don't have to manually iterate through the structure and free and do cleanup. When things go out of scope, they get cleaned up and deallocated, and that's it.

But the main issue is memory fragmentation and overallocation. Precisely the example of a JSON tree, where possibly multiple conversions are done and auxiliary structures are allocated, is where I think not all things will be allocated in a perfectly linear fashion, and therefore freeing in a stack allocator will lead to a lot of unreachable memory inside of the stack. I find it surprising that a post that talks about arena allocators doesn't even mention "fragmentation".

Are arenas a good tool? Yes, and like every good tool, they have advantages and pitfalls. This post makes it look like they're better than RAII and garbage collectors, and that's false. And the main problem isn't that it does so by virtue of having different opinions, but by hiding the pitfalls of arena allocators.

Re: Untangling Lifetimes: The Arena Allocator

#29
post #7

The author should take another look at RIIA. The first big difference is that it works with non-memory resources too, for example open/close for files. The second is that it makes heap allocated data feel a lot like stack allocated data, since the resources are ultimately owned by variables on the stack. With “move semantics” resources can be passed as arguments and returned by functions too, so the example of lifeti…

It's a C++ myth that files and memory are the same problem, in reality files are an easier problem, cf java.

?! Java doesn't offer a reasonable solution for files... it is presumed they can be closed by the garbage collector calling "finalizers", but that results in problems such as holding file locks long after they should have been released (which is a correctness problem) and running out of file handles (a limited resource that Java does not track pressure against) due to this mechanism having no time horizon.

The result is that you are essentially trapped into the realm of manual resource management, having to put a try block around every single use of a file to make sure you can control its lifetime and prevent it from "leaking" into the collector. You then would have to use a finally block and call close. Memory is certainly the easier problem as it is a single constrained resource with usage semantics (licenses and conflicts) entirely constrained by the language.

(They at least have recently added some syntax that makes the last bit of that easier, but which doesn't at all make it less manual. This syntax is somewhat based on C#'s using blocks, a feature which I might have actually caused due to some strong advocacy surrounding this issue when .NET was in beta, and yet I have always insisted this syntax failed to correctly understand the problem as, even if you buy into the manual-ness of it all, it leads to colored objects, as there are objects controlled by the garbage collector and objects controlled by using and now adding a field to an object that must be disposed flips it from one regime into the other regime without causing a type incompatibility.)

Re: Untangling Lifetimes: The Arena Allocator

#30

Earlier quoted context omitted.

> I would say RAII and Rust's borrow checker are still superior but it's definitely true that they don't work well with arenas. Note that this will definitely improve in future versions of Rust. Local allocators are an unstable feature already, and can support arena allocation.

As a C programmer who uses memory arenas quite frequently can you expand on what you know about Rust’s current or future support for such a feature? I’d like to start writing new projects in Rust and I’d like to continue to use this approach to memory management!

You can of course use arenas in Rust just like in C. I think the parent was talking about support for using arenas as the memory for stuff like built-in containers (dynamic arrays, hash maps, etc.):

https://github.com/rust-lang/wg-allocators

Post reply on HN