20 Apr 2008

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
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 :)

6 comments:

joew said...

I know you are very busy on Drakensang, but do you think it may be possible to put out one last SDK with the newest things?

Kim, Hyoun Woo said...

@Floh
Good luck of Darkensang! =)

@joew
Also there might be an other mention by Floh, we, Nebula open source community already began to talk to each other about N3 on the open community. So beg you have more time. ;-)

eRiX said...

That was a necessary fix for Drakensanng?

I still don't know much about programming. :/ but... Is this a common technique? Sounds like all apps would have that problem. How is it solved somewhere else?

And after all: how does that help the problem? If I get it right: this way the small allocations cannot intersect the large ones anymore? That all?

3Nu said...

Why don't let users to define own heap memory class?

Floh said...

@3nu: Users can also create their own local heaps by creating a Memory::Heap object and allocating from there. The only difference is that the standard heaps are visible and usable from anywhere in the code.

3Nu said...

Sorry i didn't know :D Thank you