Memory savings and metadata cache

Build 2237 introduces a number of changes aimed at making Doomsday launch faster and use less memory overall. It also fixes a couple of threading issues that were found with the help of Thread Sanitizer.

As part of preparing the stable 2.0 release, I’ve been looking at performance and memory optimizations.

Trimming memory use

I examined memory use in Instruments on macOS and identified a number of places for savings:

  • There is now a purpose-built class for keeping track of observer relationships between objects. There are hundreds of thousands of these being used in the engine, so using a class that is more optimal for the task saves both memory and improves performance.
  • Some objects had a lot of observers (20,000+) but worst of all, this was completely unnecessary because the observers were never being notified. These cases have now been removed.
  • Reduced memory used by Doomsday Script bindings for file system access by removing several unnecessary variables and replacing them with callable functions. This saves memory because functions can be stored in the class objects rather than in the objects themselves.
  • The file system caches uncompressed ZIP file contents in memory to avoid repeatedly decompressing them when the ZIP is being accessed. However, these cached contents were never released. Now ZIP caches are freed from memory whenever you return back to the Home screen.

After all these changes, Doomsday’s memory use on my system was roughly halved (from 830 MB to 460 MB). In practice, though, this heavily depends on how many resource packs and other data files you have available.

Caching metadata

When Doomsday is starting up it indexes and quickly analyzes all the resource packs, add-ons and other data files that you may have available. This may take a while depending on the number of these files and how fast your hard drive is. Starting with build 2237, Doomsday is now able to cache this information for future use, so after the analysis has been done it doesn’t have to repeated until the files change or new ones are added.

Three kinds of data is being cached:

  • ZIP archive content directories. This is essentially a list of all the files and directories inside a ZIP file. Caching this allows the file system to manipulate the ZIP archive without actually uncompressing any part of it before someone needs data from the ZIP file. Not having to uncompress ZIP files has the benefit of saving both time and memory (especially because, as mentioned above, the uncompressed ZIP contents need to be kept in memory, too).
  • WAD lump directories. Just like ZIP archives, WADs have a list of all the data lumps they contain.
  • Package metadata for data files. Doomsday 2 treats all data files internally in the same way (as packages), which means they need metadata that describes things like the package title, description, tags, readme notes, and version number. During startup, Doomsday goes through all the data files it sees and generates metadata automatically for them. However, since this involves examining the file contents in many cases, it means that any ZIP archives need to be uncompressed and the associated Info files need to be parsed. Caching the generated metadata avoids all this work.

There is also a new “Clear Cache” menu item in the DE menu that empties all the cached information. In practice, though, the cache files are quite small (a few kilobytes each) so clearing shouldn’t be necessary unless you want to force all the metadata to be refreshed.