Bitwise mark-region collection
Jon Harrop <[email protected]> Mon, 10 Jan 2011 11:04:16 +0000
| Newsgroups | gmane.comp.programming.garbage-collection.general |
|---|---|
| Message-ID | <[email protected]> |
Hi Hans, Apologies for the fresh post but I read your e-mail before I left and no lo= nger have access to it. You mentioned free lists as an alternative. That is actually exactly what m= y last prototype was doing. My free lists were stacks pointed to by the fir= st word in the region. Allocation popped a free reference off the top of th= e stack. Freeing pushed an unreachable reference onto the stack. With that = technique, sweeping was the slowest GC phase and it took around 30% of the = total running time. With the bitwise technique, sweeping is 700x faster acc= ording to my benchmarks. I identified several problems with my use of free lists: 1. Disorder accumulates in the stack-based free list unless allocation-deal= location happens to be done in FIFO order so there is no locality of refere= nce from one allocated block to the next, degrading mutator efficiency. 2. There is no way to exploit the sparsity of deallocations, which often oc= cur in contiguous runs when locality is preserved by using an allocator tha= t hands out free blocks in order. 3. The size of the free list is considerable when your allocated blocks are= as fine-grained as mine (e.g. 50% overhead when allocating 8-byte blocks). I gave more precise statistics about sparsity in this blog post: http://flyingfrogblog.blogspot.com/2011/01/importance-of-locality-and-spa= rsity-in.html Note that those results show a value being deallocated as part of a run of = 23 consecutively-allocated values is 4x more likely that it being deallocat= ed alone. I believe this is quite common in functional code and is one of t= he reasons why generational collectors have done so well there. My initial thought was, of course, to use a more sophisticated data structu= re to represent the free list in order to combat these deficiencies. For ex= ample, replacing the stack with an interval tree. Then I realised that the = size of the free list is so small that a bitvector representation would fit= into a cache line and allow the core operations to be performed on bytes o= r even whole words at a time (replacing 64 64-bit stack pops with a single = bitwise int64 AND!) whilst simultaneously providing the optimal locality of= subsequent allocation. So this bitwise approach is my evolution beyond the free list and, accordin= g to my results, it is a *lot* more efficient. Your point about cache associativity was a very good one that I had overloo= ked. However, most of the time most of the threads will be manipulating the= ir own thread-local region's bitvectors so there will be no clash and, in a= global collection of all regions, far more time will be spent marking that= rewriting these bitvectors. Loading the two bitvectors from two cache line= s in a region is sweeping 512 heap blocks whereas marking 512 heap blocks i= s likely to incur >>2 cache misses. If you made any other points that I forgot, please remind me. Cheers, Jon. Trayport Limited Registered in England at 4th Floor Rose Court, 2 Southwark Bridge Road, Lon= don SE1 9HS Company registration no.2769279.