Heap fragmentation is when available memory is broken into small, non-contiguous blocks. When this occurs,
memory allocation can fail even though there is enough memory in the heap to satisfy the request, because no one
block of memory is large enough to satisfy the allocation request.
For applications that have a low memory usage, the standard heap is adequate; allocations will not fail due to
heap fragmentation. However, if the application allocates memory frequently and uses a variety of allocation
sizes, memory allocation can fail due to heap fragmentation.
Windows XP and Windows Server 2003 introduce the low-fragmentation heap (LFH). This
mechanism is built on top of the existing heap, but as the name implies, it reduces fragmentation of the heap.
Applications that allocate large amounts of memory in various allocation sizes should use the LFH. Note that the
LFH can allocate blocks up to 16 KB. For blocks greater than this, the LFH uses the standard heap.
To use the LFH in your application, call the HeapCreate
or GetProcessHeap function to obtain a handle to a
standard heap. Then call the HeapSetInformation
function to enable the LFH. If the call succeeds, memory is allocated and freed in the LFH when you call the heap
API. Otherwise, the memory is allocated in the standard heap. Note that it is not possible to enable the LFH if
the heap was created with HEAP_NO_SERIALIZE or if you are using certain gflags options
related to the heap.
The LFH avoids fragmentation by managing all allocated blocks in 128 predetermined different block-size ranges.
Each of the 128 size ranges is called a bucket. When an application needs to allocate memory from the heap, the
LFH chooses the bucket that can allocate the smallest block large enough to contain the requested size. The
smallest block that can be allocated is 8 bytes.
The size ranges provided by the buckets are described in
the following table.
| Buckets | Granularity | Range |
| 1-32 | 8 | 1-256 |
| 33-48 | 16 | 257-512 |
| 49-64 | 32 | 513-1024 |
| 65-80 | 64 | 1025-2048 |
| 81-96 | 128 | 2049-4096 |
| 97-112 | 256 | 4097-8192 |
| 113-128 | 512 | 8193-16384 |
The first bucket is used for allocations between 1 and 8 bytes in size. The next bucket is used for allocations
between 9 and 16 bytes in size, and so on until the 32nd bucket, which is used for allocations between
249 and 256 bytes in size. The 33rd bucket is used for allocations between 257 and 272 bytes in size.
The 34th bucket is used for allocations between 273 and 288 bytes in size, and so on. The final bucket
(128th) is used for allocations between 15,873 and 16,384 bytes in size.
For example, if an application needs to allocate 10 bytes of memory, the smallest block size that can
accommodate this request is 16 bytes. Bucket two is used for allocations that are 16 bytes in size, therefore,
the LFH will allocate the memory from bucket two.
If the allocation is not a multiple of eight, there will be unused bytes. This is another form of fragmentation
called internal fragmentation. The LFH was designed to balance internal and external fragmentation.
Send comments about this topic to Microsoft
Build date: 6/12/2008