I am writing a somewhat complex game engine in Android.
Currently I have a thread used to update subsystems.
Inside the update method is the method to update game logic, which is based on current game state.
The game state has a scene, which is updated. Scenes are composed of a root node, which makes a simple scene graph structure.
Roots are nodes which have children that are also updated and so on and so forth.
Anyway, this is all nice and dandy and works great, until I get a million of these in my Logcat: 03-29 09:23:22.866: D/dalvikvm(18554): GC_CONCURRENT freed 511K, 52% free 2773K/5767K, external 77K/587K, paused 2ms+3ms
I’ve isolated the cause of the leak to be the update loop, as when I comment out my method to update subsystems, there is no GC messages. Further more, I’ve commented deep into the update loop, and up to the point where the root node’s children update is the point when the GC would run frantically.
(GameLgoic)
public void onUpdate(float deltaTime)
{
if (gameState != null)
gameState.onUpdate(deltaTime);
}
(GameState)
public void onUpdate(float deltaTime)
{
scene.onUpdate(deltaTime);
}
(Scene)
public void onUpdate(float deltaTime)
{
root.onUpdate(deltaTime);
}
(SceneNode)
public void onUpdate(float deltaTime)
{
for (int i = 0; i < children.size(); ++i)
{
children.get(i).onUpdate(deltaTime); // Memory leak runs crazily here
}
}
If I comment out children.get(i).onUpdate(deltaTime) There is no leaks! My mind is so boggled. Thanks guys.
I ran into similar problem when I made a game for Android. The only way to get out of this is to code embedded-C-Style.
So if you want a loop, reuse your counting variable, as well as your bounding variable, whenever possible, like so:
The same goes for literally everything else you touch. So you might consider to keep references to objects you don’t need anymore and to recycle them later.
It is insane what difference it made to my game implementing those changes. Framerate doubled, vast reduction of lags and so on.
You should look into the DDMS tool, which is delieverd which the eclipse Android SDK. You can use it to track down allocations, to avoid those problems.
Addtionally, you should consider removing all interators, since they are allocated everytime you jump into a loop and cannot be recycled. So it is better to loop manually and to walk through your lists multiple times (
get(x)in loop) than having to wait for the garbage collector in the long run.