mt allocator documentation (draft)

Stefan Olsson stefan@xapa.se
Fri Feb 6 14:35:00 GMT 2004


Felix Yen wrote:

> When allocating:
> >  A quick look at _S_bin[ bin ].first[ thread_id ] tells us if there 
> are any blocks
> >  of this size on the current threads freelist. If this is not NULL - 
> fine, just
> >  remove the block that _S_bin[ bin ].first[ thread_id ] points to 
> from the list
>
> When deallocating:
> >  always add the block to the end of the current threads freelist
>
> If a thread consumes all the memory it allocates, it allocates or 
> recycles some blocks in order to satisfy its first allocation request, 
> and then uses all of the blocks in this initial allocation before it 
> reuses the first one.  That might be the best approach, but it's also 
> plausible to put the deallocated blocks at the head of the free list 
> so they're reused first.  The documentation should explain why one 
> approach was chosen over the other, and should address scenarios where 
> sequences are constructed and destroyed.  (This request may lead to 
> complications.) 

I admit that I haven't thought this through. This approach was chosen on 
a "it seems like a good idea" basis. It could in fact be better (from a 
cache point of view) to add blocks to the front of the list (in case an 
application inserts and removes only a few blocks). The "last pointers" 
could also be removed then.

I feel that I need more feedback on this. Such a patch is very "doable" 
however!

>
>
> Still deallocating:
> >  In order to reduce lock contention (since this requires this bins 
> mutex to
> >  be locked) this operation is also made in chunks of blocks (just 
> like when
> >  chunks of blocks are moved from the global freelist to a threads 
> freelist
>
> When the allocator reuses blocks from the global free list, it's 
> reasonable to take a chunk's worth of blocks if possible, and as many 
> as possible otherwise.  You have to acquire a lock to accurately 
> measure the global free list's size, and once you've done this, it 
> would be strange to allocate from the heap in the case where there is 
> enough memory to satisfy the request, but less than a chunk's worth.  
> There's also no point in leaving a block in the global free list in 
> order to satisfy another thread's request. 

Not sure that I understand. As I read your comment, this is exactly what 
happens: when we have locked the global pool (in allocate()) we grab 
blocks until the end of list _or_ the amount of blocks that fits into a 
chunk. This limitation is done in order to avoid that we get "to much" 
memory on a threads freelist that then will be moved back to the global 
freelist by the deallocate() routine. This background information should 
of course be part of the documentation...

>
>
> The corresponding deallocation scenario is more complicated.  When a 
> thread's free list reaches its maximum size, you can try to move a 
> chunk's worth of blocks to the global free list, which could erase the 
> thread's free list (potentially inefficient), or do something else, 
> e.g. refer to chunk size in the maximum size computation.  The 
> documentation should provide more detail about this aspect of the 
> algorithm. 

I agree, and this should also be the piece of code that gets the most 
attention since this can further improve performance in real world 
applications. I have some ideas that I will submit at some time (when 
the doc and pending patches are done).

Brgds

/Stefan

>
>
>
> Felix
>




More information about the Libstdc++ mailing list