Thursday, August 13, 2009

Thank you for the Memory

I've been checking out - and doing some things with - the way DirectQ handles it's memory allocations. Currently there are 7 memory pools used by the engine:

  1. Memory that is allocated one time only at startup and is permanent for the duration of the run, even if the game or maps are changed.
  2. Memory that is allocated for the current game and is released and rellocated as games change.
  3. Memory that is allocated for the current map and is released and reallocated as maps change.
  4. Memory used for loading temp files.
  5. Generic scratch memory used for general purpose stuff.
  6. Memory reserved but not yet committed for loading server-side entities; this is committed as entities are loaded.
  7. A dedicated walled-off pool for the progs.dat to keep it separate from everything else.
Now, with the exception of the first 3, they all use a completely different memory allocation system. The end result is quite ugly and messy, and - as they all get managed separately - prone to error.

It's past time to make this more robust, so I'm going to overhaul this code and get a single interface at least for as much as possible.

Looking at how much memory is actually used by the engine, the Heap system maxes out at about 75 MB for warpc.bsp - so it's safe enough to assume that no other map is gonna exceed that. I currently don't have any reporting or stats on the other pools, so I honestly have no idea about how much (or little) impact on memory usage they have.

I have some ideas in my head about what the final system is going to look like - most probably a group of reserved but not yet committed pools like what's currently used for sv.edicts; but I need to work on how some of the ways DirectQ uses memory are done, particularly in relation to the huge particle support, lightmap memory mixing with texture resources, and so on.

Nonetheless, it's something that can be gradually transitioned, and will be initially a good place to be, and getting better all the time.
UPDATE

It's done, and the old heap system has been removed. I'm using VirtualAlloc for this, meaning that I can reserve HUGE blocks in the address space (I'm taking 256 MB for the map) then commit them as required. This gives all the advantages of both the old Hunk system and my Heap system. Because the blocks are just reserved in the address space, the amount of memory you have in your PC is not a factor - there are 2 GB of address space.

As an added bonus the code is now much more robust, and cleaner too, so hopefully a lot of the crazy crashes I was getting will be gone.
I've also reverted back to using compressed vis. Running directly off decompressed vis was nice for a while, but like a lot of ideas of this nature, what seems simpler on paper is not necessarily viable in the real world. In this case using decompressed vis was slowing down map loading and was also incurring a huge memory overhead - 20 MB on warpc, less on smaller maps.
Speaking of map loading times, they have been improved a lot by the new memory system. The previous one was prone to lots of small allocations syndrome, whereas this one is more able to cope with it. It's not quite at GLQuake speeds, but colossal amounts of time have been shaved off the loading speed after the server comes up, which was a major time killer in the previous release.

0 comments: