I’ve been banging my head against a wall with a hard to trace bug for a while. Would you maybe have some good insight on what I’m doing wrong?
Me and my co-workers have ported a game from XNA to MonoGame for the Windows Phone 8 but we run into problems when resuming the app too many times in a row. The resume is quite slow and then after about 4 to 6 times the app crashes.
Sometimes it seems like it might be running out of memory but then more often the stack trace points to a SharpDXException with a message “The GPU device instance has been suspended. Use GetDeviceRemovedReason to determine the appropriate action.”
Our XNA version for the Windows Phone 7 resumes and runs without problems.
This might be related to an earlier bug we had. Some of our spritesheets disappeard when the app resumed so I tried adding a function that reloads them on resume. But with ContentManager they should only get reloaded when they’ve been unloaded, right? Or would that cause unnecessary memory buildup?
Have you ever ran into the same problem and would you have any idea of how to work around this? I would love to get this sorted since this is a must fix thing for us. I like my job, I want to keep it
Thank you in advance!
EDIT: This seems to be a memory management issue in my code. If you have any tips about memory management with MonoGame I’d be happy to hear them! Thanks!
Yes, I can confirm it seem to be a memory leak. Coming from the same team as “Ihmelaama” I just ran some tests, it looks like that app memory usage (ApplicationMemoryUsage) grows between resumes, until it hits the limit (ApplicationMemoryUsageLimit).
There is a memory leak for sure - somewhere. Here’s a code that just loads a 4MB texture and then sits still. Switching back and forth between the app and OS (e.g. pressing Windows and back buttons) shows that the app eats gradually more and more memory (megabytes) in every turn.
If you guys have ANY ideas, please let us know. We have a game to be published soon and this is a major issue for us with 512MB devices, e.g. popular Lumia 520.
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Phone.BackgroundAudio;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace MonoGameSample
{
public class Game1 : Game
{
const int TEXT_NUM = 10;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D testTexture;
Anyway, workaround seem to be to call Content.Unload (or Content.Dispose) in OnDeactivated. Obviously you need to load everything back when resume. Need to test more…
EDIT: Content.Unload and Content.Dispose seem to be a no-go. They don’t consume more memory, but they don’t free it up properly either. After resume you are forced to reload content and we face the same issue again - more and more memory is consumed after every resume. Bummer, I’m running out of options here…
Ville, I tested with threads too. Created own content mgr in a separate thread. In OnDeactivated told thread to dispose texture and content, then killed the thread. When back after resume, recreated the thread and asked it to load texture again. No luck. I didn’t even draw the texture, just loaded it with content manager. 4BM memory (texture size) wasted in every resume.
Is there any alternative content manager available somewhere?
Update for those who may be interested. We ended up with this workaround:
Reduced the active content size to minimum, using spritesheets with compression and loading compressed sound FX only when needed
Disposing content manager and forcing carbage collection with GC.Collect in OnDeactivated routine
Recreating content manager and reloading content in OnActivated
Not the most sophisticated resolution, but it works and doesn’t crash low end WP phones anymore. Available memory still wanders between resumes in a peculiar way, but it eventually stays below the limit.
I hope the root cause gets resolved one day. My guess is a memory leak either in Monogame or SharpDX, ie poor ContentManager memory handling in hold/resume situations.
I am also seeing this behavior. Unfortunately your workaround does not seem to have solved my problem. The memory usage still wanders upwards, albeit slower than before.