XNA WP7 Texture memory and ContentManager
- by jlongstreet
I'm trying to get my WP7 XNA game's memory under control and under the 90MB limit for submission. One target I identified was UI textures, especially fullscreen ones, that would never get unloaded.
So I moved UI texture loads to their own ContentManager so I can unload them. However, this doesn't seem to affect the value of Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage"), so it doesn't look like the memory is actually being released.
Example: splash screens. In Game.LoadContent():
Application.Instance.SetContentManager("UI"); // set the current content manager
for (int i = 0; i < mSplashTextures.Length; ++i)
{
// load the splash textures
mSplashTextures[i] = Application.Instance.Content.Load<Texture2D>(msSplashTextureNames[i]);
}
// set the content manager back to the global one
Application.Instance.SetContentManager("Global");
When the initial load is done and the title screen starts, I do:
Application.Instance.GetContentManager("UI").Unload();
The three textures take about 6.5 MB of memory.
Before unloading the UI ContentManager, I see that ApplicationCurrentMemoryUsage is at 34.29 MB. After unloading the ContentManager (and doing a full GC.Collect()), it's still at 34.29 MB. But after that, I load another fullscreen texture (for the title screen background) and memory usage still doesn't change.
Could it be keeping the memory for these textures allocated and reusing it?
edit: very simple test:
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
PrintMemUsage("Before texture load: ");
// TODO: use this.Content to load your game content here
red = this.Content.Load<Texture2D>("Untitled");
PrintMemUsage("After texture load: ");
}
private void PrintMemUsage(string tag)
{
Debug.WriteLine(tag + Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage"));
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
if (count++ == 100)
{
GC.Collect();
GC.WaitForPendingFinalizers();
PrintMemUsage("Before CM unload: ");
this.Content.Dispose();
GC.Collect();
GC.WaitForPendingFinalizers();
PrintMemUsage("After CM unload: ");
red = null;
spriteBatch.Dispose();
GC.Collect();
GC.WaitForPendingFinalizers();
PrintMemUsage("After SpriteBatch Dispose(): ");
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
if (red != null)
{
spriteBatch.Begin();
spriteBatch.Draw(red, new Vector2(0,0), Color.White);
spriteBatch.End();
}
base.Draw(gameTime);
}
This prints something like (it changes every time):
Before texture load: 7532544
After texture load: 10727424
Before CM unload: 9875456
After CM unload: 9953280
After SpriteBatch Dispose(): 9953280