1.2.1 Private Heaps and Contention

The most serious performance problem afflicting heaps in a multithreaded environment is contention. Standard heap algorithms protect the internal data structures of the heap by preventing more than one thread at a time allocating from the heap or releasing memory back to it. The protection is achieved by surrounding sensitive sections of the heap management code with locks. If a thread tries to access the heap but finds it locked by another thread, it must sleep until the other thread has cleared the critical region and released the lock. Heap contention triggers frequent, time-consuming context switches and may cause significant performance degradation for multithreaded applications, especially when running on multiprocessor machines. If somehow each thread could have its own heap, contention would not occur.

A DLL produced by the Microsoft Visual C++ compiler (under particular linker options) creates its own private heap when it initialises. The private heap is for use by certain C (or C++) run-time library facilities. The heap is created automatically by startup code and the programmer is unaware of its existence. The heap is created regardless of whether the program actually calls any C run-time routines. Consequently it is not unusual to find a modest application spawning thirty heaps, many of which are barely used.

In addition to these implicit heaps, it is common programming practice for a DLL to create ad hoc private heaps, perhaps one dedicated to each important data type. Such behaviour has to be explicitly coded.

Oddly enough, DLL-private heaps do not solve the heap contention problem, since several threads may concurrently be traversing the routines that the DLL exports. DLL-private heaps mitigate contention on the statistical ground that if there are lots of heaps, the chances of two threads accessing the same heap at the same time are low.

To eliminate contention and to allow the useful optimisation of skipping over the expensive locking instructions used in the heap routines, it is necessary for each heap to be private to a particular thread. This may be achieved programatically by creating a heap as each thread starts.