Memory

Started by
10 comments, last by rip-off 14 years, 10 months ago
Hi, im re-writting my game engine because i came accross a couple of good snags in why it shouldnt be used one of them was memory management, I dont really know much about it but ive searched the internet a fair bit etc and still not sure what im looking for i was told good memory management needs to handle garbage and fragmentation stuff etc, I was wondering if anyone has found a decent article or something from a book that could help me :) if not atleast point me in the right direction thnx for any help and apologies for a probably well answered question that i n00bishly cant seem to find
Advertisement
From my understanding unless you're going to make some good money off the engine, memory management isn't worth the hassle. Firstly it involves overloading the new operator so you actually know how much memory is being used and were its being created. Forcing objects to be created in chunks that wont separate them across ram and so forth. I'd look into the benefits against the time it takes to implement it, then ask your self why you want it.
[ dev journal ]
[ current projects' videos ]
[ Zolo Project ]
I'm not mean, I just like to get to the point.

first question is, how much memory are you allocating? and how often are you allocating memory?

basically, all good engines use some form of pool allocator. at startup, the engine will grab a bunch of large blocks of contiguous memory (ie: pools) and will allocate out of those pools, instead of using the bare heap.

why do this? well, it comes down to how you access memory. and if your writing a teeny game with a handful of objects, its really probably not worth doing, but if you want to have big scenes, with lots of objects, particles, etc, using a pool system becomes very useful. for the following reasons.

- you can allocate different pools to different kinds of memory (eg: graphics resources in GPU friendly ram).
- for objects which are both small, and allocated frequently (like particles) using a pool will massively reduce heap fragmentation (as only the pool will get fragmented). and you can happily 0 the entire pool when your not displaying particles, eliminating fragmentation entirely.
- it puts a hard limit on the size of your resources, and the memory footprint your game will use. if you run out of memory, you will know exactly where, and why.
- using a pool for level objects, means that when you leave the level, you can simply 0 the entire pool. no more leaks (as long as nothing is holding resources which point to the pool of course!).
- you can defragment a pool at runtime. of course doing this means that anyone holding a reference or pointer to your data must be holding a weak pointer to it. this is generally a good idea anyway, boost has one you can use.
- you can garbage collect from pools at runtime. usually using a reference counted system. can be useful, but also needs things like dead pool lists to keep objects around for a few frames until downstream references are released, etc.

on large games (ala commercial titles), each subsystem will get its own pool, and maximum budget. and its up to each subsystem to dole out memory from that pool as it sees fit. the UI subsystem might get 20mb of ram, out of which needs to come fonts, UI, textures, etc. the resource system might grab 256mb of ram, 128mb of which is a pool for models, 64mb for textures, and 64mb for level objects.. etc etc.

For your own stuff, having a few different pools can be useful, having a separate pools for things like particles is a godsend (and even if you only use pooling for particles, it still helps a lot), and a separate pool for your level objects. can make life a lot easier.

It really comes down to how often, and how much memory your allocating. allocating a lot of very small objects, and then deleting them shortly afterwards will not make the heap a happy place.

personally, ive had it drilled into me over various console tiles to avoid the heap like the plague . There are lots of great pool allocator algorithms out there (eg: slab) but its only worth it if your allocation patterns are problematic.
your never as good as they say you were, never as bad as they say you was.
A simple memory manager used in a lot of commercial games is the mark/release system: 1, 2.

From my perspective, the rules of YAGNI/KISS mean that Garbage collection (other than simple reference-counting) and Defragmentation is a waste of time.
Quote:Original post by Hodgman
A simple memory manager used in a lot of commercial games is the mark/release system: 1, 2.

From my perspective, the rules of YAGNI/KISS mean that Garbage collection (other than simple reference-counting) and Defragmentation is a waste of time.


I agree, its worth getting some pools in, get some simple ref counting going. and if you really need it, you can bolt on defragging later. (as long as you adhere to the pointers to things in pools being weak pointers).


your never as good as they say you were, never as bad as they say you was.
Quote:Original post by sarriss696
i was told good memory management needs to handle garbage and fragmentation stuff etc


This is only true if you really want to go that route, i.e. try to come up with a 100% managed memory system. In that case, I suggest you code directly in Java, C# or Python or some other language that offers a fully managed environment. Note that even those don't do automatic defragmentation as far as I know (although there's no reason why they couldn't), since in modern PCs the address space is just large enough to avoid the issue.

Very often in games (and especially on consoles), memory management is not just handled as a black box, but the actual game code is designed to work with the best practices of using memory resources. This means that the memory management layer offers the game layer support code like shared_ptrs, memory pools, arenas, heaps and other abstractions that the game programmer finds convenient. In the context of consoles with small amount of memory, it is preferred to have the game programmer manually organize the data loading so that fragmentation is avoided, instead of indirecting your memory accesses through relocatable memory handles that would do defragging automatically for you.

In summary, memory management in unmanaged setting is not a black box, and good memory management lets the game programmer *avoid* memory leaks and fragmentation from occurring (instead of trying to solve it after it has occurred).

Don't know about any of this and don't even want to care about any of this? Use Java, C# or Python, they will (mostly) make memory issues go away, and you can focus on your game instead.
Thank you all for the very quick replies,

tbh my game so far will probably be fairly small,

so yes memory management might not really be neccessary but i plan on building on this game slightly later one with things like multi-texturing etc, and i got told things like that eat away at your memory,so while im building my engine from scratch again I thought now would be a good time to put in memory management and ive had to learn it from scratch,

pain in the backside lol and i must admit the other languages sound tempting but im afraid i have to stick with C++, for particular reasons that probably would full up the forum database lol,

Thnx for the help with options and definatly thnx for the good explanations you all provided, they were a very helpful insight into what i need to look into and what i Should be looking into, pools sounds like fun hehe :D

thnx all :)
Quote:Original post by clb

Note that even those don't do automatic defragmentation as far as I know (although there's no reason why they couldn't)


Generational garbage collection performs "defragmentation" on each garbage pass. As surviving old data gets copied into new heap, it also compacts the memory.
Quote:Original post by Antheus
Quote:Original post by clb

Note that even those don't do automatic defragmentation as far as I know (although there's no reason why they couldn't)


Generational garbage collection performs "defragmentation" on each garbage pass. As surviving old data gets copied into new heap, it also compacts the memory.


Oh, thanks for the correction!
I don't think that anyone has mentioned that a correctly implemented pool is lightning fast to allocate from. If you implement your pools as freelists of same-sized objects, then allocation and freeing from the pool is only a few cycles. A heap allocation can be hundreds of cycles. Another advantage of freelists is that they don't suffer from fragmentation at all. So there is no need for any fancy runtime defragmentation system.

Freelists can use slightly more memory if you dont know how many objects of that type/size you need (because you need to have enough free in the freelist). If you know exactly how many of a certain object you will have in a level (trees/plants/rocks for instance) then you can create a freelist with that number of free objects when you load the level.

You could even allocate another chunk from the heap when the freelist runs out and stick that chunk at the end of the freelist to make it more dynamic.

This topic is closed to new replies.

Advertisement