Any way to catch memory fragmentation on windows?
#4 Members - Reputation: 571
Posted 17 October 2012 - 08:45 AM
Edit: unless you mean you want to see if your code is fragmenting your own memory, in which case the virtual memory system has no effect, because as far as your program is concerned it just has one giant block of contiguous memory. To see if you have internal fragmentation, you'd have to use your own memory management system to keep track of what memory is free and what memory is taken, and at some time print / save / whatever a graphical representation of the memory. You can then see how bad the fragmentation gets.
Edited by turch, 17 October 2012 - 08:56 AM.
#5 Members - Reputation: 1971
Posted 18 October 2012 - 04:12 AM
For example, std::vector uses a very unhealthy allocation pattern if you keep pushing back data without reserving. It will first allocate a larger block, copy data, and then free the smaller block. STB Vorbis (if I remember correctly, might be the reference Vorbis implementation, too) uses a similar pattern to determine the length of a soundfile.
Physical memory is fragmented into 4k chunks (some of it possibly in 1M chunks with large page support) either way, there is nothing you can do about it, and no reason why you should care. It does not affect you or the system in any way, this is just as it's supposed to be.
Edited by samoth, 18 October 2012 - 04:13 AM.
#6 Members - Reputation: 3830
Posted 18 October 2012 - 04:33 AM
If you still insist, then you can use the Heap* API calls on Windows (HeapAlloc, HeapFree, etc), and every now and then make a call to HeapCompact, which will clean things up for you: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366598%28v=vs.85%29.aspx
It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.
#7 Moderators - Reputation: 13602
Posted 18 October 2012 - 04:33 AM
Assuming you're concerned about fragmentation within your own address space, and not physical fragmentation:Oh. Is there any way to track memory fragmentation on Windows then? Or maybe Linux?
Every game engine I've used has had an optional "memory tracking mode", which is usually #ifdef'ed out. This mode adds extra code to every new/delete/malloc/free call to keep a log of every allocation.
You can use this log for many purposes, like seeing which lines memory leaks came from, or how much memory different game systems are using, or the order in which things are created.
Usually the engine will also provide some external tools to inspect these logs, such as visualizing all allocations as pixels in a 2D image. Large allocations might take up many rows of pixels, while small allocations might just be dots. If you see lots of tiny empty spaces between allocations, that's fragmentation.
For an example of what this typically looks like, check out Elephant and Goldfish.
On PC, using default allocators, this really isn't much of a problem. New/Malloc simply aren't going to fail due to fragmentation... unless maybe you've got 4GiB of data allocated at once... PC has a huge address space to play with, so it's ok to be naive about efficient memory usage.
Memory fragmentation is a much bigger issue on consoles, where maybe you've only got 256MiB of RAM! On these systems, it's easy to end up in a situation where you've got 200MiB allocated, with 56MiB free, however that 56MIB is actually spread over 50 different ~1MiB blocks, so asking for 10MiB will fail.
My advice to avoid fragmentation would be to unlearn the idea that you can just grab/release memory with new/delete whenever you feel like it, and instead be much more structured in how you allocate things. E.g. if you know a level has a maximum of 100 monsters alive at once, then at the start of the level, make a pool containing 100 monsters - then you don't have to allocate new ones whenever they spawn using new/delete, you can get them from the pool.
In my engine, I treat new/malloc as a "global variable", which means their use is banned for being evil.
Another thing you can do is stop using pointers to refer to objects. If you use other identifiers, then you can support relocating objects.
e.g. if you had a collection of up to 256 Objects, and you wanted to be able to move those objects to support de-fragmenting memory, you could use a table like:
struct Table
{
Object* addresses[256];
Object* GetObject( int id ) { return addresses[id]; }
}which means you can reallocate an object somewhere else, and just update the table to point to the new allocation. Anyone "pointing" to the object via an id doesn't have to know that it's moved. DotNET and Java do this behind the scenes, thanks to not using pointers.e.g. if when transitioning from level1 to level2, you know that 50% of the currently loaded assets are going to be used by the next level, you can free the unneeded level1 assets, then you can move the remaining ones to ensure there's no wasted space between them, and then load the new level2 assets knowing there's no fragmentation.
Edited by Hodgman, 18 October 2012 - 04:50 AM.






