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
Those heap types may change in the future, I'm not sure yet, whether these are too many or too few types. I'll add some more status information to the memory HTTP debug page handler with statistics data about the different heap types, so it should be easy to see whether this configuration is good or not. Also, the Nebula3 code doesn't have that many calls to Memory::Alloc() or Memory::Free() (around 20..30 or so), so it's relatively easy to try out different usage patterns. Of course it's still possible to create a special local heap using the Memory::Heap class. On a side note: as you may have noticed, my posting frequency has suffered a lot recently. The reason is that I'm now 110% focused on Drakensang, there's just not enough time left to do a lot of work on N3 or on the blog. Don't expect this to change until around mid-July :)