4 ms·
The tricky part with allocators is always the multi-threaded setups. Even something as simple as a bunch of threads doing malloc-free in a loop will drop perfo
by huhtenberg 7y ago
The tricky part with allocators is always the multi-threaded setups.
Even something as simple as a bunch of threads doing malloc-free in a loop will drop performance of a lot of allocators to the floor, due to some sort of central locking or excessive cache thrashing. This is typically solved by adding per-thread block pools, free lists or some such.
If you go further down the rabbit hole, there's a case when blocks are allocated in one thread and freed in another, your very typical producer-consumer setup. This too further complicates things with the pool/freelist setup and requires periodic rebalancing of freelists and pools.
So once all this is accommodated, a well-tuned allocator inevitably converges to a model with central slabs/pools/freelists and per-thread caches of the same, which are periodically flushed into the former. Then it all comes down to routine code optimization to make fastpaths fast, through lock-free data structures, some clever tricks and what not.
In other words, it's always nice to read through someone's allocator code, but in the end this is a very well-explored area and there's basically a single stable point once all common scenarios are considered.
- pjmlp 7y agoTo the point you really need specialized knowledge. I remember DrDobbs and The C/C++ Users Journal having ads for companies whose sole product was a memory allocator for different kinds of deployment scenarios.
- AndrewStephens 7y agoAnd those products really did help. Microsoft's implementation of malloc performed terribly for many workloads - dropping in a 3rd party allocator could speed up your software considerably. It wasn't until well into the 2000s until the standard allocators started to become good enough to make the 3rd party libraries less essential. Many of them you can still buy today and they probably still help with certain types of software.
- fabrice_d 7y agoThey claim to perform well on at least some multi-thread workloads (read https://github.com/microsoft/mimalloc#performance https://github.com/microsoft/mimalloc#performance): "The larson server workload allocates and frees objects between many threads. Larson and Krishnan [2] observe this behavior (which they call bleeding) in actual server applications, and the benchmark simulates this. Here, mimalloc is more than 2.5× faster than tcmalloc and jemalloc due to the object migration between different threads. This is a difficult benchmark for other allocators too where mimalloc is still 48% faster than the next fastest (snmalloc)."
- Veedrac 7y agoThere are a lot of ways to write the same story; Mimalloc has a few innovations of its own, has good benchmarks to justify them, and the paper is a very good read. In particular, Mimalloc works to increase data locality, by using per-‘page’ (64kB memory blocks) free queues. All this with a codebase almost a tenth the size of jemalloc, and it's looking very promising.
- trianglesphere 7y agoIt's a little hidden, but this is out of MS research, and seems to be initially designed for ref-counted scripting languages. I'm not really sure how much they focused on multi-threaded stuff. >We present mimalloc, a memory allocator that effectively balances these demands, shows significant performance advantages over existing allocators, and is tailored to support languages that rely on the memory allocator as a backend for reference counting. https://www.microsoft.com/en-us/research/publication/mimalloc-free-list-sharding-in-action/ https://www.microsoft.com/en-us/research/publication/mimallo...
- Veedrac 7y agoThat's not what the quote means, really. They have best-in-class performance on both single- and multi-threaded workloads. It is just saying that the allocator supports a deferred_free callback, which is zero-overhead in the fast path and negligible overhead in the slow path.
- bakery2k 7y agoWhat if I'm writing code that's strictly single-threaded? Presumably malloc could be simpler and/or faster in this special case? Is there a production-ready allocator that's optimized for single-threaded use?
- gok 7y agoIt's very hard to not accidentally pull in a dependency that makes your code multithreaded.
- 01100011 7y agoYou guys could argue this all day and both be right. Depending on what type of system you're working on, you are either very likely to pull in a multithreaded dependency or you are not. Systems programming is different from game programming is different from web client programming is different from kernel development. In most of my career, I would have never accidentally pulled in a multithreaded dependency, but I could see how that could be easy to do in some cases.
- imtringued 7y agoIt is already faster because there is no lock congestion.
- rurban 7y agoFor this use case a good copying collector would be best. Beats any malloc by miles.
- pizlonator 7y agoThis allocator appears to have some genuinely interesting things in its multi thread support: - it looks like it avoids atomics on common cases of malloc and free. That’s a big deal and not all malloc a accomplish that. - it looks like it has cleverness specifically for the case that one thread frees an object into another thread’s heap. It seems like this case was given some special consideration - in particular avoiding the need for the thread that owns the heap to stop or synchronize at the moment that happens even though that thread is non-atomically allocating and freeing in that same heap. So, it’s always easy to sound smart by saying that a field is well explored - but it looks like this thing actually has some cool new ideas in it.
- gpderetta 7y ago>it looks like it avoids atomics on common cases of malloc and free. That’s a big deal and not all malloc a accomplish that. Many mallocs implementations try to avoid one cache per thread because it can waste a huge amount of memory in applications with thousands of threads opting for per cpu pools or similar solutions. These solutions help with contention but still require atomics (unless using something like restartable sequences). It is a trade-off, but for applications that use one thread per cpu, completely private free lists can branch win of course.
- emeryberger 7y agoAll modern allocator implementations I am aware of (including Hoard and Mesh) use per-thread caches (of a limited size), and thus avoid the use of atomic operations in the common case while also avoiding blowup (wasted memory caused by using a memory allocator that "leaks" -- see the Hoard paper (ASPLOS 2000, https://people.cs.umass.edu/~emery/pubs/berger-asplos2000.pdf https://people.cs.umass.edu/~emery/pubs/berger-asplos2000.pd...) for a full discussion).
- pizlonator 7y agoDoes hoard avoid atomic ops on the common case of both malloc and free?
- Quekid5 7y agoAndrei Alexandrescu had a great talk[0] on allocators and this convinced me that if you really care about allocator performance[1] what you need is a tunable and composable system. The whole idea of how and when (runtime/compile-time) to choose the appropriate allocator is also interesting. [0] https://www.youtube.com/watch?v=LIb3L4vKZ7U https://www.youtube.com/watch?v=LIb3L4vKZ7U [1] I suppose there's a digression to be had here about allocation being trivial and RAII-style deallocation not really being deterministic, but...
- jasonwatkinspdx 7y agoYou should actually read the technical report: https://www.microsoft.com/en-us/research/uploads/prod/2019/06/mimalloc-tr-v1.pdf https://www.microsoft.com/en-us/research/uploads/prod/2019/0... This has some quite clever and very carefully considered details around concurrency. > in the end this is a very well-explored area and there's basically a single stable point once all common scenarios are considered. I think it's absurd to call allocation a solved problem where there's one known optimal design.
- yason 7y agobut in the end this is a very well-explored area With a lot of interesting new generic allocators that beat the competition hands down popping up in the last 10 years, I'd dare to claim the area is not very well explored. It has indeed been explored a lot but it seems that there's still low-hanging fruit. Every few years someone writes an allocator that makes significant improvements over the previous generation implementations. I love to see such action on "solved problems".
- plietar 7y agoYou may want to look at snmalloc, another allocator we did at Microsoft Research. It specifically targets these producer / consumer scenarios. https://github.com/microsoft/snmalloc https://github.com/microsoft/snmalloc And the paper, which I’ll be presenting tomorrow at ISMM: https://github.com/microsoft/snmalloc/blob/master/snmalloc.pdf https://github.com/microsoft/snmalloc/blob/master/snmalloc.p...