[SOLVED] Memory leak in my game

Hi all!

I’m sorry to bother you all, but I’ve run out of options.
I’ve been experiencing the weirdest thing for some time now.
I have a MonoGame project, windows desktop, 3.5, and when running in VS using the included mem-profiler and the one from RedGate they say I leak about 12k each level-load. It loads graphics and sounds there.

When I run it at home, my computer has a good video-card, I get about that in the task-manager as well.

But when I run it on my company’s laptop, it leaks about 300MB per level load up to the point when the system starts freezing…
Don’t know if it’s important or not, but the laptop has only some small shared video card…

Has anyone ever experienced that behavior before? Of course I will provide further data on the topic.

It’s probably a stupid mistake on my side or something everyone knows about.

So most likely this is a memory leak somewhere in your draw() function.

There are a few classes that you absolutely cannot create new instances of for every frame (without deleting the old ones) - SpriteBatch, Texture2D, RenderTarget etc.

These should be created once and then reused, because the garbage collector does not remove them from memory. You need to do that manually with .Dispose()

Check if you create them every frame!

The easy way to find memory leaks is to run DEBUG -> Performance and Diagnostics -> Memory Usage (or performance wizard)


Thank you so much kosmonautgames!

I just finished doing a very long memory-profiling session and found some discrepancies.
Your hints were very helpful.

I’ve managed to find almost all of the leaks, if I dare to believe in the various profilers (down to 1k).
The problem was that the profilers showed only about 18k leaking yesterday, but the task-manager showed about 300MB on my laptop and about 80MB on my desktop (the leaks are per level-load; so 300MB leak per level is a huge thing).

I still don’t know why those numbers differ that much. Would be very interested in knowing why.
Guess that the memory-allocation strategies are extremely dependent on the version of the OS (windows 7 <-> 10).
Or the mem-profilers (VS and RedGate alike) show only the reason, but not the full extent of the consequences of the leak.

Anyways, the numbers in the taskmanager on my desktop are down to almost zero now and I’ll update this post with the new numbers from the tuned version on the laptop tomorrow.
Thanks for your time.

For completeness here are the measurements with the old code and the results that left me puzzled:

VS 2015 community edition says that the diff is about 5-6k.

Redgate says about the same thing (10k).

But on the laptop, when I watch the taskmanager, the difference is about 300MB!

That seems odd.

So… WTF? I honestly don’t know how that happens…

This is the new version recorded with the profiler:

This one is done with a dedicated profiling-session as kosmonautgames suggested:

You see that the leak is down to about 340bytes.
But on the laptop, again…

You see it’s about 300MB again…
What’s happening here? I must be missing something… something embarrassing obviously…
How can all the profilers record such low leakage if the task-manager shows such a large leak?

If those objects have managed GPU resources then .NET will see them as relatively small (less than 100 bytes) while in reality they reserve MBs of data.

What are those 12 objects? Can you make it to load the first stage every time? In that case the number of objects between snapshots has to be the same (0). Otherwise there is some leak of objects. Don’t forget to call GC.Collect() at the end of stage loading just to be sure that all released objects are collected.

Oh. That actually makes sense. Thx.
I call GC.Collect() alright but I will examine those 12 objects further. That’s a leak alright as they keep piling up…
I think they are SharpDX Direct3D objects, but I don’t know for sure.
Would explain a lot (size) actuallly…

But it has to wait until tonight.

I just freaked out because of the huge difference and the difference between my laptop (~300MB) and my desktop (~100MB).
I’ll keep posting.

I just freaked out because of the huge difference and the difference between my laptop (~300MB) and my desktop (~100MB).

I don’t have an explanation for that. Maybe it’s due to diferent GPU/drivers, or the GPU shares system memory.

Sorry, but I have to postpone till tomorrow. Cleaning up takes a lot longer than suspected :slight_smile:

And the cleaning up still continues ;(

Ok. I’ve reduced it to zero.
But still the memory consumption rises. Maybe I’ve overlooked something in my code (most probably) or maybe not, but I decided to move to the develop-build of MonoGame (previously I used the 3.5.1 release installer).

So, after doing that (I’ve updated the repo, built the windows-solution and copied the tools-build over the MSBuild/MonoGame/v3.0-Folder and referenced the new build in my game) and now, after the content pipeline did some rebuilding, I get a DivideByZeroException when creating SoundEffectInstances like here:

That happens now with every wav-file I have…
The files worked before (minutes ago with 3.5.1) and the XNB files were re-built.
The wav-files are std. Audacity-output wav-files. Some stereo, some mono.
I feel that I’ve read about this somewhere here on the board, but I cannot find it… Any pointers?

Ok. I’ve set up a test-project after using the installer of the develop brach in TC and I found out that that error always happens with every single wav file if the quality is below ‘BEST’ like here:

So you always get that error if you select ‘Medium’ or ‘low’, but it works if you select ‘best’.

Is that a know bug?

btw, that boost my game from 260MB to 570MB :slight_smile:

It’s been reported here.

Use the 3.5.1 build tools for sounds. (You might have some issues with effects, I think the format has changed since 3.5.1)

But still the memory consumption rises. Maybe I’ve overlooked something in my code (most probably) or maybe not, but I decided to move to the develop-build of MonoGame (previously I used the 3.5.1 release installer).

Maybe you have to Dispose some objects, it’s really hard to tell.

Yeah. I know.
I’m disposing like hell :slight_smile:
Thanks for the tip for the sound-issues. I will try that tonight.

For the sake of completeness:
I had another issue upgrading concerning Effects. Was a mistake on my side, of course. I loaded a few effects for each of my sprites and the mistake was they all had their own ContentManager. So there was no de-duplication.
Odd thing is, with the old version it used some VRAM alright, but was OK. With the new version I got outofmemory-exceptions when loading the effects.
I fixed my broken code; But I wanted to tell someone.

Update: I’ve managed to get the new version of MG up and running. Had to use the ‘old’ pipeline tool for re-encoded audio (medium or low), but it works now.
One odd thing though which I wanted to mention; Obviously the content-loader for sound-effects was synchronized in the previous version; Now it’s not any longer :slight_smile:. Had to lock it myself. Since all resource-loading by the ContentManager should be considered non-thread-safe, that’s ok IMO, but it definitely changed behavior.

Tomorrow I will continue my hunt for the leak…

@nkast I see that this issue you referenced is closed? Is that ok since the problem seems to still exist?

It’s still open but I have the felling it flew under the radar. Perhaps the title is too specific but I didn’t want to post a duplicate issue. I posted my findings on the issue but at the moment I don’t have the time to look into the code for a PR.

Uh. Sorry. My mistake. You only referenced the closed issue. My bad.

OK. Done profiling and refactoring.
It shouldn’t come much as a surprise that the leak was indeed Texture2Ds not being disposed because of freakish ContentManager constellations in my code. The textures then remained somewhere in memory where the profiling tools couldn’t see them… didn’t investigate further, but sounds legit.

In my defense I have to say that it’s pretty old and that I was young… and I needed the money… :smile:

Now I cleaned up the majority of those problems; Disposing of ContentManagers where I had to generate them to get rid of the loaded assets on exit of a menu-screen for example; Not disposing of single textures any longer while the ContentManager would accidentally remain loaded, and so on and so forth.

Thank you all for being supportive and pointing me in the right directions despite of this being the 1002nd ‘my-game-leaks’ thread…

Great community!