Modern object-oriented software spends up to half of its time allocating and deallocating objects. The performance of your memory allocator is therefore critical.
The Lightwave Memory Manager (LMM) is a C/C++ library that replaces the new/delete/malloc/free that are provided by your compiler. Lightwave is a memory-manager that is designed for speed, and as a result applications using LMM can experience a remarkable boost in performance.
Performance
| Threads | Data range (bytes) | malloc (million allocations per second) |
Lightwave (million allocations per second) |
| 1 | 1000 | 3.8 | 8 |
| 1 | 10000 | 2 | 6.3 |
| 2 | 1000 | 3.4 | 9.4 |
| 2 | 10000 | 1.8 | 6.9 |
| 4 | 1000 | 5.2 | 10.4 |
| 5 | 10000 | 2 | 6 |
| 8 | 1000 | 8 | 18.4 |
| 8 | 10000 | 1.6 | 5.6 |
Lightwave outperforms malloc on the leading compiler by a factor of 2-3. The improvement is especially noticeable on multi-processor/multi-core systems.
Libraries
The simplest way to use LMM is to link the file lmm_mallocnew.lib with your application. lmm_new redefines the default new and delete, and your application's code is completely unchanged. lmm_malloc.lib redefines malloc/free, while lmm_mallocnew.lib redefines all of the functions.
Thus it is very easy to make the switch to LMM and back again.
lmm.lib
If you don't want to override malloc/new, you can use the core library, lmm.lib. To use LMM in this way, include the file lmm.h, which provides the functions
If you #include <lmm_malloc.h>, it will #define malloc to lmm_malloc, free to lmm_free, and realloc to lmm_realloc. #include lmm_new.h to defines new and delete operators that use LMM. lmm_malloc.h and lmm_new.h should normally be included in pre-compiled headers.
Multi-threaded programs
If your program uses a fixed number of threads, your program will work fine with LMM. However if it creates lots of threads dynamically, you must call lmm_release() upon thread exit. This is because LMM needs to free memory allocated in thread-local storage.
Potential problems
LMM uses a bit more memory than normal memory allocators because it allocates memory in anticipation of future requests. Thus if you have allocated lots of objects of a particular size, the allocator anticipates future requests of that size. If you free objects, it won't immediately release that memory, but will hold those objects in a list ready for fast servicing of future memory requests. To reduce locking overhead, it stores some data in thread-local storage, so if you have a lot of threads, you may end up using more memory than if the memory was pooled between threads. Use the function lmm_set_thread_cache() to tune this value, which set to 1MB by default.
LMM limits that overhead to around 20%, and the speed gained more than compensates for this extra caching in most circumstances.