ggambett
10-03-2004, 12:45 PM
This post continues the spirit of the classic Dexterity threads Shrink that installer! (http://www.indiegamer.com/archives/t-1053.html) and Shrink that installer Part II (http://www.indiegamer.com/archives/t-1440.html). I want to share my recent experiences with the memory footprint of a game.
Why
I got the ocassional Betty's Beer Bar crash report where the game failed with an "out of memory" error. At first, since the game is 5 MB compressed, I thought the machines were already short of memory, but after adding logging code for that, I found out that was not the case - BBB was dying even when it had 80-90 MB free memory at start.
So I wrote a little script to calculate the size of every image in the game; to my amazement, BBB's 4.8 MB of datafiles packed 96 MB worth of pixels! Not counting the images that are generated at runtime by pasting some images over another images to make the animation frames.
But it's worse : I implemented lazy loading of images, and in compliance with the KISS philosophy that guides my life (Keep It Simple, Stupid), I never unloaded them - it's some sort of very simple cache. Of course, I didn't realize it was 96 MB.
What
My other problem is that, also because of being lazy, all the frames of a given animation have the same size, regardless of the actual size of that particular frame, for easier compositing. Of course, empty and transparent pixels compress very well, that's why I could pack that 96 MB into less than 5, but they are fully expanded in memory.
So what I did was adding yet another preprocessing step to my already complex build process. Every image is autocropped, and its original size and position are stored in a spec file. At load time, this spec is read, and the Image class (which is over 2000 lines of code - and blitting is done somewhere else) has been modified to have the notion of a "virtual canvas" - externally, the image behaves exactly as if it had the original dimensions.
The tricky part is adjusting the blitting wrappers to correctly handle virtual over physical, physical over virtual, and virtual over virtual. The "over virtual" cases may resize the physical size of the image while maintaining the virtual size if the image blitted over it would use space that was previously cropped.
Conclusion
All in all, doing this took about 4 hours including testing, and all the images now take 38 MB. It's still a lot, but it's the minimum possible, and only 40% of the original size. It also probably loads faster and compresses slightly better.
Lessons learned :
- Do YOU know the memory footprint of your game?
- Having cleanly designed classes and respecting encapsulation lets you do this kind of complex thing without touching even one line of client code.
I hope this was useful for someone!
Why
I got the ocassional Betty's Beer Bar crash report where the game failed with an "out of memory" error. At first, since the game is 5 MB compressed, I thought the machines were already short of memory, but after adding logging code for that, I found out that was not the case - BBB was dying even when it had 80-90 MB free memory at start.
So I wrote a little script to calculate the size of every image in the game; to my amazement, BBB's 4.8 MB of datafiles packed 96 MB worth of pixels! Not counting the images that are generated at runtime by pasting some images over another images to make the animation frames.
But it's worse : I implemented lazy loading of images, and in compliance with the KISS philosophy that guides my life (Keep It Simple, Stupid), I never unloaded them - it's some sort of very simple cache. Of course, I didn't realize it was 96 MB.
What
My other problem is that, also because of being lazy, all the frames of a given animation have the same size, regardless of the actual size of that particular frame, for easier compositing. Of course, empty and transparent pixels compress very well, that's why I could pack that 96 MB into less than 5, but they are fully expanded in memory.
So what I did was adding yet another preprocessing step to my already complex build process. Every image is autocropped, and its original size and position are stored in a spec file. At load time, this spec is read, and the Image class (which is over 2000 lines of code - and blitting is done somewhere else) has been modified to have the notion of a "virtual canvas" - externally, the image behaves exactly as if it had the original dimensions.
The tricky part is adjusting the blitting wrappers to correctly handle virtual over physical, physical over virtual, and virtual over virtual. The "over virtual" cases may resize the physical size of the image while maintaining the virtual size if the image blitted over it would use space that was previously cropped.
Conclusion
All in all, doing this took about 4 hours including testing, and all the images now take 38 MB. It's still a lot, but it's the minimum possible, and only 40% of the original size. It also probably loads faster and compresses slightly better.
Lessons learned :
- Do YOU know the memory footprint of your game?
- Having cleanly designed classes and respecting encapsulation lets you do this kind of complex thing without touching even one line of client code.
I hope this was useful for someone!