Live data from Hacker News

Arena allocator tips and tricks

nullprogram.com

71–80 of 99 posts

Re: Arena allocator tips and tricks

#71

> Unsigned sizes are another historically common source of defects, and offer no practical advantages in return. Case in point exercise for the reader: Change each ptrdiff_t to size_t in alloc, find the defect that results, then fix it. I know that it’s a different “kind” of defect, but none of the code has overflow checks even with ptrdiff_t…

Why would it need overflow checks when subtracting two valid pointers?

Re: Arena allocator tips and tricks

#72
post #50
post #49

Earlier quoted context omitted.

Adding that when many linux distributions face OOM, a killer daemon steps in and might kill your service even if you were handling the situation properly.

Interestingly (confusingly), Linux's OOM killer is invoked for a different notion of OOM than a null return from malloc / bad_alloc exception. On a 64-bit machine, the latter will pretty much only ever happen if you set a vsize ulimit or you pass an absurd size into malloc. The OOM killer is the only response when you actually run out of memory. If you want to avoid your program triggering the OOM killer all on its o…

I wonder if it is possible to avoid OOM by making sure that all allocations are done from a named (on disk, not shm) memory file. This way in principle is always possible to swap to disk and never overcommit.

I guess in practice the kernel might be in such dire straits that it is not able to even swap to disk and might need to kill indiscriminately.

Re: Arena allocator tips and tricks

#73

Earlier quoted context omitted.

Welp. Linus Torvalds was right about this stuff. https://lwn.net/Articles/316126/ https://lkml.org/lkml/2003/2/26/158

Wait until someone tells Linus about how processors do reordering. (Yes, I know he understands it. Clearly he just refuses to accept that compilers can also reorder his code and he needs to accommodate that.)

In fairness, CPU reordering is does not visibly affect a thread view of their own loads and stores.

Re: Arena allocator tips and tricks

#74

Earlier quoted context omitted.

> Having to decide ahead of time how much memory to allocate to the arena is... crap... A nice solution in many cases is to just keep a bunch of std::vector (or equivalent) around for the types you need, and .clear() them all at the start of each request/frame/message/whatever being processed. Calling push_back on a vector will only allocate when the vector's already reached its capacity, which will happen very rarel…

Generally, std::vector not going to work for allocator backend. The issue being, std::vector relocates all elements every time it increases the capacity. Therefore, adding an element to std::vector may invalidate addresses of all previously added vector elements. You gonna have to adjust your higher-level data structures which use that allocator, replacing pointers with offsets relative to the start of that std::vect…

std::deque, although it would be nice to use an implementation where you can control the block size.

Re: Arena allocator tips and tricks

#75

Earlier quoted context omitted.

Generally, std::vector not going to work for allocator backend. The issue being, std::vector relocates all elements every time it increases the capacity. Therefore, adding an element to std::vector may invalidate addresses of all previously added vector elements. You gonna have to adjust your higher-level data structures which use that allocator, replacing pointers with offsets relative to the start of that std::vect…

std::deque, although it would be nice to use an implementation where you can control the block size.

Here’s a simple non-standard allocator for C++ I used a few times in the past: https://github.com/Const-me/CollectionMicrobench/blob/master...

The block size is controlled with a template argument, the number must be a compile-time constant.

Re: Arena allocator tips and tricks

#76
post #50

Earlier quoted context omitted.

Interestingly (confusingly), Linux's OOM killer is invoked for a different notion of OOM than a null return from malloc / bad_alloc exception. On a 64-bit machine, the latter will pretty much only ever happen if you set a vsize ulimit or you pass an absurd size into malloc. The OOM killer is the only response when you actually run out of memory. If you want to avoid your program triggering the OOM killer all on its o…

I wonder if it is possible to avoid OOM by making sure that all allocations are done from a named (on disk, not shm) memory file. This way in principle is always possible to swap to disk and never overcommit. I guess in practice the kernel might be in such dire straits that it is not able to even swap to disk and might need to kill indiscriminately.

You would also need to prevent overcommit of disk; you'd typically mmap to a sparse file, and then you've got the same problem of overcommit on disk as you did in memory.

If you're going to do drastic things, you can configure Linux's memory overcommit behavior, although strictly avoiding overcommit usually results in trouble from software not written with that in mind.

Re: Arena allocator tips and tricks

#77
There is also the double-sided arena allocator which uses one contiguous buffer but grows in both directions (front-to-back and back-to-front). When allocating memory from it you need to indicate whether you want memory from the front or back. The allocator is out-of-memory when both font and back meet.

The double-sided approach is useful for various purposes. For instance you can allocate short-lived data from the front and long-lived data from the back. It also makes better use of free space: with two separate arena allocators one could be out-of-memory but the other might have free space. With the double-sided approach all memory is fair game.

Re: Arena allocator tips and tricks

#78
post #67
post #49

Earlier quoted context omitted.

Adding that when many linux distributions face OOM, a killer daemon steps in and might kill your service even if you were handling the situation properly.

The idea is that the server must have a known allocation budget, similar to Java's max heap size. There's a tree of allocators, i.e. a temporarily created arena allocator needs initial memory for its arena, so it can grab it from the root allocator. And the root allocator ultimately must be fixed-size and deterministic. Sure if there are other processes in the system allocating without concern for other apps, then th…

You can disable the OOM killer on your server OS:

https://www.kernel.org/doc/Documentation/vm/overcommit-accou...

Re: Arena allocator tips and tricks

#79
post #30

Earlier quoted context omitted.

As a share of the total number of programs written this is a minority indeed. How many pls are out there vs the number of libraries/apps? The number of deploys is a different thing.

Almost every program written in some programming language depends on the runtime provided by this programming language. Very few programming languages even let you to opt out of using the runtime. Which means that if the runtime needs something, then your program also needs it. Complexity doesn't magically go away when you put it into a library

It’s not so much about using the code as it is about writing the code (or at least, providing utilities to the code being written). Yes every program uses the runtime, but very few people write the runtime. That is, perhaps the default provided to end users should be arena allocators, keeping a general malloc for special cases.

Re: Arena allocator tips and tricks

#80
"Without individual lifetimes, you don’t need to write destructors, nor do your programs need to walk data structures at run time to take them apart."

Destructors are a very bad idea if you are using any form of garbage collection other than reference counting. The destructors won't run until some arbitrary time after the last access to the object, and in the case of arenas, what would be a very fast deallocation becomes proportional to the number of objects. Further, if destructors can revive objects, everything gets very complicated.

Post reply on HN