The implementation choices for a heap manager make a lot more sense when you consider what happens after a large number of allocations and deallocations.
A call to malloc()
needs to locate a block of unused block of sufficient size to allocate.
It could be bigger (in which case, it could either create a free block with the difference - or waste it). A naive strategy of finding the closest size of block is called best fit. If it goes onto to create new free blocks, you could alternatively call it worst leave.
After use, the best-fit approach results in a large amounts of fragmentation, caused by small blocks that are unlikely to be ever allocated again, and the cost of searching the free blocks becomes high.
Consequently, high performance heap managers don't work like this. Instead they operate as pool allocators for various fixed block-sizes. Schemes in which the blocks are powers of 2 (e.g. 64,128,256,512...
) the norm, although throwing in some intermediates is probably worthwhile too (e.g. 48,96,192...)
. In this scheme, malloc()
and free()
are both O(1)
operations, and the critical sections in allocation are minimal - potentially per pool - which gets important in a multi-threaded environment.
The wasting of memory in small allocations is a much lesser evil than fragmentation, O(n)
alloc\dealloc complexity and poor MT performance.
缓存行大小的最小块大小是那些经典的工程权衡之一,可以肯定的是,微软做了很多实验来达到64
他们的最小值。FWIW,我很确定您会发现现代 CPU 的缓存线大小比这更大。