Ask HN: What is your favorite hand-rolled malloc?
In a similar vein to http://graphics.stanford.edu/~seander/bithacks.html, I'm curious to hear the people's choice for memory pool/slab allocators. My question is a three-parter:
1) Allocation size function: Do you allocate fixed size chunks of N objects at a time? Exponential increase in chunk size (I believe valgrind does this for its memchecker)? If exponential, do you also back off exponentially, or linearly? Something else?
2) Used/free record keeping: Bitfield? Linked-list? Other?
3) New allocations: realloc or array/linked list of pointers (I bet I know the answer to this one)?
Some justification would be nice, if you've got the time.
19 comments
[ 0.15 ms ] story [ 44.2 ms ] threadIt's been a long long time since I rolled my own, so I don't think I'm qualified to answer the rest of your questions except for the second, linked list of pointers of free(d) memory would be the best choice I think, with as an extra an array of such lists grouped by size. (I hope that makes sense...) to speed up the search for a block of the right size.
We allocated fixed size chunks of N objects, although we didn't have a smooth function for what the chunk size was. The inflection points where we changed our strategy were cache-line size and page size.
Used/free record keeping was a simple table to map an address to the data structure for that address, and we re-used the free memory for an internal list.
That's what we did to get good sequential performance - it was the multithreaded performance we were interested in. Aiming for good multithreaded performance influenced the data structure design to be simpler to reduce synchronization.
Details are in the paper and source code.
Can you tell us more about your specific problem? Then we'd be able to give suggestions and help evaluate the options.
There are some other issues with the same piece of code that need re-working, and we'll end up with a totally different approach by the end, so I don't really have a problem that needs a crowd solution; I was just curious what everyone here thinks.
I use arena allocators when I can get away with it. Arenas are absolutely trivial to code; there's no per-object "free", so allocation is just a pointer bump. You will be surprised at how often you can get away with this; lots of allocation-heavy code paths map to a single operation, transaction, request, file, or what-have-you, and all you're doing is deferring free to the end of it. Using arenas in this scenario basically erases the cost of allocation from your program. It's also dramatically harder to fuck up.
For anything else, when malloc hits the top of my profile, I have a simple freelist library for pools of homogenous allocations, with an embedded linked list of free items.
You could get smarter than an arena, a generic freelist, and malloc, but why?
My story:
- Profiled the code to figure out allocation sizes and number of allocations.
Can you tell me yours? With such detail, then perhaps we can figure out what's best for you? :-)Where I have had big advantages over libc malloc is where the memory allocations have been specific to a thread context. For example, consider a multi-threaded server, where by you could guarantee that only one thread was active in a connection at anyone time. It's quite easy for a single connection to spend 5-10% of it's time in malloc and there are often big globalish locks around general purpose allocators, so it's easy to get get mutex contention which is far worse than the overhead of a sub-efficient allocator.
In such cases you often need to have small bits of memory within the context of a connection. Here I found big benefits my mallocing memory in bug chunks and then simply splitting that up into small sections within a connection specific allocator to avoid any malloc mutex locking.
What I've found is that in order to beat normal malloc, I think you really have to have a specific usage case that restricts something to do better.
A paper about it:
http://goog-perftools.sourceforge.net/doc/tcmalloc.html
The code:
http://code.google.com/p/google-perftools/