Memory Issues
The 2 most critical issues with dynamic memory allocation seem to be memory leaks and memory fragmentation. While memory leaks can be discovered and fixed easily, memory fragmentation is harder to come by since it usually only shows up when the application runs for many hours. At some point, allocation of large memory blocks may fail even though the total amount of free memory is more then enough to satisfy the request. I have recently added some counter-measures to Drakensang, which I have ported over to Nebula3 during the last 2 hours. The basic idea is to go away from the general Memory::Alloc()/Memory::Free() and to group allocations by usage pattern into different heaps, so that small, large, short-lived or long-lived memory blocks are not allocated all from the same heap. Nebula3 now defines various global HeapTypes, which need to be provided as arguments to the Memory::Alloc() and Memory::Free() functions. Platform ports of Nebula3 are free to define additional platform-specific heap types, as long as only platform-specific code uses those new types. The platform-specific code also has full control over the initialization of the global heaps (like the initial heap size, or whether the heap is allowed to grow or not), which is especially important for console platforms with their restricted amount of memory and no page-file-swapping. For now I have arbitrarily defined the following heap types:
- DefaultHeap: for stuff that doesn't fit anywhere else
- ObjectHeap: for RefCounted objects (this may be split into more HeapTypes in the future)
- SmallBlockHeap: general heap for small allocations
- LargeBlockHeap: general heap for "large" allocations (several megabytes)
- ResourceHeap: for long-lived resource data, like animation keys
- ScratchHeap: for short-lived memory blocks
- StringHeap: for string-data
- StreamDataHeap: used by classes like MemoryStream or ZipFileStream