Torque X huge memory leak - Fixed
by Giuseppe De Francesco · in Torque X 2D · 03/18/2010 (11:54 am) · 298 replies
Well,
I'm not sure this is the right place to post this, maybe the blog? At any rate I'm posting here now.
Torque X has a huge memory leak, but seriously! I was working to a RPG game for a start so I didn't really notice, but 2 weeks ago I started YASS, a multiplayer side scrolling space shooter: a lot of particles, really a lot, and a lot of projectiles as well.
To let you understand here follows a short video of the game:
This is the memory situation after 3 minutes of gameplay (single player!!!) the game slowed down a lot:

So, I searched the forum and I realized that this issue is an old one and GG never got a grip on it (go figure why...) so I decided to fix the problems myself because I really need to publish YASS ;)
Long story short: I revised the whole engine and made a lot of fixes, some of them really of great importance, so here it is the situation playing my game (as you can see after 9 minutes the game still is 20% less than the original 3 minutes!):

There are still many stuff to fix, but at any rate in the current state I'm able to publish the game ;) I will make the SVN diff files available upon request (free of charge: pino AT dftgames DOT com).
Cheers,
Pino
I'm not sure this is the right place to post this, maybe the blog? At any rate I'm posting here now.
Torque X has a huge memory leak, but seriously! I was working to a RPG game for a start so I didn't really notice, but 2 weeks ago I started YASS, a multiplayer side scrolling space shooter: a lot of particles, really a lot, and a lot of projectiles as well.
To let you understand here follows a short video of the game:
This is the memory situation after 3 minutes of gameplay (single player!!!) the game slowed down a lot:

So, I searched the forum and I realized that this issue is an old one and GG never got a grip on it (go figure why...) so I decided to fix the problems myself because I really need to publish YASS ;)
Long story short: I revised the whole engine and made a lot of fixes, some of them really of great importance, so here it is the situation playing my game (as you can see after 9 minutes the game still is 20% less than the original 3 minutes!):

There are still many stuff to fix, but at any rate in the current state I'm able to publish the game ;) I will make the SVN diff files available upon request (free of charge: pino AT dftgames DOT com).
Cheers,
Pino
About the author
In the software eng. field since 1981, in charge of R&D during last 10 years. IEEE Senior Member (and volunteer).
#102
When a scene object is registered it decides what scenegraph to add itself to using the following code in T2DSceneObject::OnRegister()
As you can imagine this is problematic if it gets the wrong scenegraph - which is possible because the database doesn't return the most recently loaded scenegraph like you might expect it to, so objects can end up in a scenegraph different from the one that was loaded with the scene [the one you thought they would be in].
This also can cause issues for objects loaded at runtime, since they also use the same code to decide which scenegraph to add themselves to. In short, it doesn't look like multiple scenegraphs was well designed for in TX.
Anyway, I address this issue from two directions. Firstly, I replace the code with this:
So now the code always gets the default named scenegraph (DefaultSceneGraph being the name that the editor assigns automatically). And once a scene is loaded I explicitly name the scenegraph that just got loaded so I know there is only every going to be one scenegraph called DefaultSceneGraph [the one for a scene that is being loaded - all loaded scenes have properly named scenegraphs]. So when a scene is loading all the objects will get the right scenegraph (alternatively you could have the scene loader directly set the scenegraph on the newly loaded objects, but I wanted to mod the engine a minimal amount in this instance).
Secondly, for objects created at runtime I will explicitly set their scenegraph when I create them.
This way I make sure that all objects, whether loaded from a scene file or created at runtime, will end up in the proper scenegraph/s.
hth
03/28/2010 (5:59 pm)
@Matt: the torque database has a nasty little thing it does when you ask it to find objects. If you don't provide a name to search for then it will return the first object of the correct type that it finds (not necessarily the most recently loaded one). Normally you won't notice this, but in the case of the scenegraphs and multiple simultaneous scenes it can become an issue. I'm not sure, but this might be related to the issue you are having, so I'll give more details in case it's helpful.When a scene object is registered it decides what scenegraph to add itself to using the following code in T2DSceneObject::OnRegister()
_sceneGraph = TorqueObjectDatabase.Instance.FindObject<T2DSceneGraph>();
As you can imagine this is problematic if it gets the wrong scenegraph - which is possible because the database doesn't return the most recently loaded scenegraph like you might expect it to, so objects can end up in a scenegraph different from the one that was loaded with the scene [the one you thought they would be in].
This also can cause issues for objects loaded at runtime, since they also use the same code to decide which scenegraph to add themselves to. In short, it doesn't look like multiple scenegraphs was well designed for in TX.
Anyway, I address this issue from two directions. Firstly, I replace the code with this:
_sceneGraph = TorqueObjectDatabase.Instance.FindObject<T2DSceneGraph>("DefaultSceneGraph");So now the code always gets the default named scenegraph (DefaultSceneGraph being the name that the editor assigns automatically). And once a scene is loaded I explicitly name the scenegraph that just got loaded so I know there is only every going to be one scenegraph called DefaultSceneGraph [the one for a scene that is being loaded - all loaded scenes have properly named scenegraphs]. So when a scene is loading all the objects will get the right scenegraph (alternatively you could have the scene loader directly set the scenegraph on the newly loaded objects, but I wanted to mod the engine a minimal amount in this instance).
Secondly, for objects created at runtime I will explicitly set their scenegraph when I create them.
This way I make sure that all objects, whether loaded from a scene file or created at runtime, will end up in the proper scenegraph/s.
hth
#103
03/29/2010 (2:07 am)
Do these fixes get rid of the jump/glitch due to Garbage Collection? I noticed no matter what I did, I couldn't get the game to stop the "glitching" that happens every 10 seconds or so. Profiling tools have shown what seems to the be the engine creating a whole bunch of strings and objects during runtime. If your fixes do get rid of this, I can safely buy the source and patch...
#104
My shooter YASS (early version in the video) can now be played by 4 people with continous firing (and firing SFX, time interval 100ms) and full of explosions and I do not see any "jumping" anymore.
03/29/2010 (4:03 am)
@Charlie: the answer is "yes and no" :) meaning that all the jumpy behaviour caused by the engine itself are gone, still your own code might provoke some glitching, so if after this fix is applied there are still a few of those then I assume is the game itself :)My shooter YASS (early version in the video) can now be played by 4 people with continous firing (and firing SFX, time interval 100ms) and full of explosions and I do not see any "jumping" anymore.
#105
Duncan I'll give that a go. Thanks again for taking the time to help.
I'm battle-ling though the last of my leaks. I'm down to components that have been disposed but are not getting Garbage Collected. I'm figuring once I get those to release properly most of my other issues will go away :).
03/29/2010 (7:15 am)
Thanks for the info guys.Duncan I'll give that a go. Thanks again for taking the time to help.
I'm battle-ling though the last of my leaks. I'm down to components that have been disposed but are not getting Garbage Collected. I'm figuring once I get those to release properly most of my other issues will go away :).
#106
03/29/2010 (11:24 am)
Can I please grab a copy of the patch? This is exciting :) My email is bryant@sprybry.com. Thanks!
#107
Thank you.
notplana@msn.com
03/29/2010 (2:03 pm)
If you can play YASS on xbox with four people without code 4in' then that is amazing. We cant run more than three different zombie types at once without getting a code four and I always suspected that it was somehow programming related. Now I have proof, I would very much appreciate this.Thank you.
notplana@msn.com
#108
I created a started GUI TX3D Pro game. I have the standard terrain in it, though I did scale it some.
On Windows it takes 108 ms to load as noted in the output window of the debugger. I added some simple code to the TorqueSceneData _LoadObjects method to tell me on the xBox how long it was taking to load each object because the default profiler stuff only compiles on the PC build.
Anyway, on the xBox it takes 20799 ms to load the exact same terrain object.
Everything else takes a ton longer as well, but this one is very significant. Could memory leaks be the cause of it or are we dealing with something else?
03/29/2010 (4:39 pm)
I am wondering if anyone else has seen what I am seeing in the 3D stuff. I know Pino is working on that next, but didn't know if this is related.I created a started GUI TX3D Pro game. I have the standard terrain in it, though I did scale it some.
On Windows it takes 108 ms to load as noted in the output window of the debugger. I added some simple code to the TorqueSceneData _LoadObjects method to tell me on the xBox how long it was taking to load each object because the default profiler stuff only compiles on the PC build.
Anyway, on the xBox it takes 20799 ms to load the exact same terrain object.
Everything else takes a ton longer as well, but this one is very significant. Could memory leaks be the cause of it or are we dealing with something else?
#109
Also if you deploy to xbox from from Visual Studio in debug mode it will show you the ms load time in the output window for you just like it does in windows - if I remember correctly.
03/29/2010 (5:17 pm)
Xbox can have issues with slow file access during dev. Once released on XBLIG it tends to be a lot faster in that respect.Also if you deploy to xbox from from Visual Studio in debug mode it will show you the ms load time in the output window for you just like it does in windows - if I remember correctly.
#110
I created a Torque GUI 2D Starter game with the new engine.
Next I created a level with just the GG sprite and attached the movecomponent to it.
I created a new Component Named "TestComponent" and leave the new components code unmodified.
I hooked this Component to the GG sprite with the movecomponent on it.
In the movecomponent I added the following:
The restart code
In my memory profiler I find that if I take a snapshot of the game after unloading the scene both components are Disposed but have not be garbage collected.
If I reload the game and then re-exit I find that a new snapshot shows that new copies of the components have been created and the old ones are still trapped in memory.
Thanks again for the help. Feel free to tell me to bug off. :)
03/29/2010 (10:03 pm)
Heya Pino, I may have found an issue with components not disposing. The last Memory Errors I have are with my components that are disposed but not garbage collected, so I did a test.I created a Torque GUI 2D Starter game with the new engine.
Next I created a level with just the GG sprite and attached the movecomponent to it.
I created a new Component Named "TestComponent" and leave the new components code unmodified.
I hooked this Component to the GG sprite with the movecomponent on it.
In the movecomponent I added the following:
void _OnBackButton(float val)
{
if (val > 0.0f)
{
Game.Instance.ReStartGame();
}
}The restart code
public void ReStartGame()
{
Game.Instance.SceneLoader.UnloadLastScene();
GuiStartScreen startScreen = new GuiStartScreen();
GarageGames.Torque.GUI.GUICanvas.Instance.SetContentControl(startScreen);
}In my memory profiler I find that if I take a snapshot of the game after unloading the scene both components are Disposed but have not be garbage collected.
If I reload the game and then re-exit I find that a new snapshot shows that new copies of the components have been created and the old ones are still trapped in memory.
Thanks again for the help. Feel free to tell me to bug off. :)
#111
Disposed instance
9 types have instances that have been disposed but not GCed.
Investigate the types below for more information.
T2DCollisionComponent, T2DCollisionMaterial, T2DPhysicsComponent, T2DSceneCamera, T2DSceneGraph, T2DStaticSprite, MovementComponent, TestComponent, TestComponent2
Instance queued for finalization
One type has instances that are queued for finalization. This can indicate that a Finalizer method is stuck, which will prevent instances from being finalized and cause memory leaks.
Investigate the type below for more information.
DepthStencilBuffer
Undisposed instances (release resource)
One type has instances that have been garbage collected without being properly disposed.
Investigate the type below for more information.
System.Drawing.Icon
03/29/2010 (10:17 pm)
my list of Memory profiler errors after unloading a scene in the starter project as described above.Disposed instance
9 types have instances that have been disposed but not GCed.
Investigate the types below for more information.
T2DCollisionComponent, T2DCollisionMaterial, T2DPhysicsComponent, T2DSceneCamera, T2DSceneGraph, T2DStaticSprite, MovementComponent, TestComponent, TestComponent2
Instance queued for finalization
One type has instances that are queued for finalization. This can indicate that a Finalizer method is stuck, which will prevent instances from being finalized and cause memory leaks.
Investigate the type below for more information.
DepthStencilBuffer
Undisposed instances (release resource)
One type has instances that have been garbage collected without being properly disposed.
Investigate the type below for more information.
System.Drawing.Icon
#112
1) There are no root or strong references involved.
2) If I take 5 snapshots over 10 minutes (so every 2 minutes) the number of objects disposed but not GCed doesn't grow, so it looks like a GC issue because over time they are being removed.
The above reasoning doesn't mean that I dismissed the issue, I'm just disregarding it while more serious problems are found. I made this work mostly at night and in the fastest possible way so not all the use cases have been covered (actually only a few of them) and some code I wrote is redundant, I put it there just to be on the safe side but it's now time to clean it up while new issues are discovered in other use cases: I'm getting some feedback via email as well and those take priority ;)
At any rate do not stop posting your findings: it's great to have more feedback and pointers ;)
03/30/2010 (4:02 am)
@Matthew: First off, thank you very much for the feedback, it's very helpful! I noticed that list of objects not CGed but I disregarded it at the moment for two reasons: 1) There are no root or strong references involved.
2) If I take 5 snapshots over 10 minutes (so every 2 minutes) the number of objects disposed but not GCed doesn't grow, so it looks like a GC issue because over time they are being removed.
The above reasoning doesn't mean that I dismissed the issue, I'm just disregarding it while more serious problems are found. I made this work mostly at night and in the fastest possible way so not all the use cases have been covered (actually only a few of them) and some code I wrote is redundant, I put it there just to be on the safe side but it's now time to clean it up while new issues are discovered in other use cases: I'm getting some feedback via email as well and those take priority ;)
At any rate do not stop posting your findings: it's great to have more feedback and pointers ;)
#113
03/30/2010 (7:28 am)
Awesome thanks for working on this. :)
#114
Secondly, as a paying customer(like most everyone else here), I would like to see some official involvement from the GG guys on this issue. Some kind of statement from them that they acknowledge this issue and it will be officially addressed instead of relying on a community fix(a great one btw) to make the product perform like it should have when it was released.
To me, this is like buying a new car, and then having to figure out why it isn't running quite right without any dealer involvement.
With the supposed new commitment to TorqueX, I figured they would at least be in on this thread helping resolve the issues.
03/30/2010 (10:32 am)
First of all. Great work guys on fixing these issues. It makes TorqueX 2D a usable engine for game development.Secondly, as a paying customer(like most everyone else here), I would like to see some official involvement from the GG guys on this issue. Some kind of statement from them that they acknowledge this issue and it will be officially addressed instead of relying on a community fix(a great one btw) to make the product perform like it should have when it was released.
To me, this is like buying a new car, and then having to figure out why it isn't running quite right without any dealer involvement.
With the supposed new commitment to TorqueX, I figured they would at least be in on this thread helping resolve the issues.
#115
03/30/2010 (12:43 pm)
@Jason: I have the GG people in the list so they got all the fixes. I don't know if they'll apply them to the official version or they'll use it as pointer to the issues, but for sure nobody will get any more official update without all these issues addressed because it'll be a huge step backward (to the Code 4!).
#116
to avoid further problems with the application of the diff files I've splitted the project in 3 small repositories and reset the version numbering. All the people in the current distribution list will get an invitarion email to get direct access to the SVN repositories (according with the owned licence as shown in GG forum).
The system has a bug management as well so please use it to signal problems ;)
03/30/2010 (12:54 pm)
Guys,to avoid further problems with the application of the diff files I've splitted the project in 3 small repositories and reset the version numbering. All the people in the current distribution list will get an invitarion email to get direct access to the SVN repositories (according with the owned licence as shown in GG forum).
The system has a bug management as well so please use it to signal problems ;)
#117
03/30/2010 (1:27 pm)
I've just received my invitations. Thanks, Pino!
#118
03/30/2010 (1:40 pm)
Thanks for the Invite :).
#120
03/30/2010 (3:25 pm)
would be interested in getting a copy of you mods. Can you send info to finitezero@hotmail.com. Thanks in advance
Associate Giuseppe De Francesco
DFT Games Ltd
thanks for pointing that out. The whole deserializing structure needs to be revised because of many small issues. Looking at the loader my feeling is that has been expanded by different people having different approaches so I find it quite hard to follow when it comes to its internal structure: it's a task that will take time. I can't exclude that now that the objects are properly disposed we'll face strange behaviours manipulating directly the object database.
As you found a work around I won't put this as a priority task, leaving it in the planned task about the scene deserialirer which I'll work after having consolidate the TX3D library to work with the fixed shared Core.
Thanks for the pointer ;)