3 ms·
> And while a bump allocator can be simple and efficient for a single-threaded program, in a multi-threaded program like Go it requires locks. In general it's
by pcwalton 9y ago
> And while a bump allocator can be simple and efficient for a single-threaded program, in a multi-threaded program like Go it requires locks. In general it's likely to be more efficient to allocate memory using a set of per-thread caches, and at that point you've lost the advantages of a bump allocator.
Ian is extremely confused here. Every production multithreaded generational GC uses thread-local allocation buffers (edit: thanks to Filip for correcting my terminology).
- pizlonator 9y agoVery few production multithreaded generational GCs use per-thread nurseries. But probably all of them use thread-local caches, or what you might call per-thread caches. I think that's what you might have meant. Per-thread nurseries is a shit idea unless your language has extra-super-high levels of infant mortality. Remember that in a per-thread nursery genGC, the write barrier has to infect the pointed-to object with the global heap so that future stores to that object also trigger the barrier. In a normal genGC, the pointed-to object is unaffected; the stored-to object is merely shaded (or card-marked, or logged, or whatever) for revisiting. Humorously for parent's post, to my knowledge the first instance of a thread-local cache was the idea that a multithreaded compacting GC can chop off a slice of memory from the global bump allocator and then use it to service a thread-local allocator. Not 100% sure though because maybe Boehm and friends beat everyone to it.
- pcwalton 9y ago> Very few production multithreaded generational GCs use per-thread nurseries. > Per-thread nurseries is a shit idea unless your language has extra-super-high levels of infant mortality. Isn't that what TLABs are? HotSpot uses TLABs by default, unless my info is out of date… For example, [1] shows the generated assembler for object allocation, which uses nonatomic pointer bumps. I think we might be talking about different things by "per-thread nurseries". All I mean by a "per-thread nursery" is a TLAB. [1]: https://shipilev.net/jvm-anatomy-park/4-tlab-allocation/ https://shipilev.net/jvm-anatomy-park/4-tlab-allocation/
- pizlonator 9y agoLike I said, you're thinking thread-local caches. TLABS are thread-local caches, not per-thread nurseries. There's a HUGE difference between a thread-local cache (which everyone uses and which you cite) and per-thread nurseries (which are an obscure idea that hardly anybody likes).
- pcwalton 9y agoYes. Apologies for using the wrong terminology :)
- geodel 9y agoAnd TLABs causes more memory fragmentations and which lead to more GCs and more need for memory compaction. So finally Java solved the problem it created itself by implementing compacting and generational GC.
- pcwalton 9y agoWhat? TLABs allow a bump allocator with copying collection, which results in the least kind of fragmentation you can possibly have—zero! How can TLABs increase fragmentation?
- geodel 9y agoYou can read at: https://www.thinkmind.org/download.php?articleid=icons_2012_8_10_20033 https://www.thinkmind.org/download.php?articleid=icons_2012_.... "Thread-local allocation buffers (TLABs) are widely used in memory allocators of garbage-collected systems to speed up the fast-path (thread-local allocation) and reduce global heap contention yet at the expense of increased memory fragmentation. Larger TLABs generally improve performance and scalability but only up to the point where more frequent garbage collection triggered by increased memory fragmen- tation begins dominating the overall memory management overhead. Smaller TLABs decrease memory fragmentation but increase the frequency of executing the slow-path (global allocation) and thus may reduce performance and scalability..."
- pcwalton 9y agoThat isn't relevant to what we're discussing here. The problem of fragmentation across arenas that that paper describes is a problem with any system that uses thread-local caching, including Go's tcmalloc. The type of fragmentation we're discussing is fragmentation within a memory arena. That is the kind of fragmentation that only a copying/compacting collector can eliminate.