1
\$\begingroup\$

I'm making my first game with LibGDX and Box2D, and I've realized that the memory used increases when I change screens. It starts from 150MB and progressively reaches 850. How should I deal with this? It does not seem to be a memory leak, memory is constant throughout the level, and I'm using an AssetManager to dispose everything needed.

The problem is when switching screens, since objects remain in memory. What is the best practice in this case? Should I have a method in each class that sets every object to null before the screen is disposed? Another problem might be that I have a static class for all my constants (this was the method proposed in the Udacity course), could this be an issue?

Another idea described here is initializing all screens in the beginning and using them throughout the game. Though I'm not sure this could be done in my game now. Is this good practice?

I tried profiling a bit although it's the first time, here are some results. The sudden 'hops' are when switching screens. enter image description here

\$\endgroup\$
  • \$\begingroup\$ If you dispose everything but the memory usage doesn't drop it usually means you have references to the object that hinder the garbage collector to clean up. I suggest to read how to properly use the asset manager and in which order objects have to be disposed. Order of disposal might play a role. \$\endgroup\$ – D3d_dev Aug 17 '19 at 6:00
  • \$\begingroup\$ Thanks for answering. What about setting objects to null, is that generally implemented in games when disposing a screen? Also do you think initializing all screens in the beginning and using them throughout the game is a good idea? \$\endgroup\$ – xmac Aug 17 '19 at 16:19
0
\$\begingroup\$

Setting objects to null might not guarantee proper disposal. Usually an asset manager has some kind of reference counter for every used asset. It is better to use dispose instead of setting to null and waiting until the destructor call happens via garbage collector. It is better because the dispose happens instant and you have better control when memory is freed and stuttering can occur on large disposals. Understand that if you dispose the asset manager clears cpu and gpu memory for e.g. a texture. Initializing all screens is only a good idea if your game size is very small and you want achieve faster level switching. Otherwise it is a bad practice because you waste system resources for content that isn't even consumed by the player. The general rule is to only allocate as much as absolutely required and as less as possible. That's the whole point of loading screens. Less memory allocated = able to support older hardware = bigger playerbase.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ But what about class objects used by other classes? These have nothing to do with the assets and the Asset Manager. How should memory occupied by these be freed, if not by setting these objects to null? \$\endgroup\$ – xmac Aug 18 '19 at 17:30
  • \$\begingroup\$ Either Make sure your non asset classes properly implement the dispose pattern and call dispose on level or don't bother at all and let the gc do it's job risking stuttering during gameplay. Events are known to produce memory leaks so just unsubscribe.But before dispose you have to save your settings to a game state. Game state can be very simple as singleton and every level load checks the game state settings and on unload writes some values like points, health, etc. Just make sure with a profiler that your objects are properly freed. Profiling is an essential tool here. \$\endgroup\$ – D3d_dev Aug 18 '19 at 20:26
  • \$\begingroup\$ In general define lifetime for each object and make sure you free properly without memory leaks due to subscribed events or not properly using the dispose pattern. If you know lifetime you can design object disposal in a way that the garbage collector does not randomly kick in and make your game stutter during gameplay. Dispose and allocation are for loading screens or need finer tactics like in open world games where load balancing and dynamic allocation is a thing. \$\endgroup\$ – D3d_dev Aug 18 '19 at 20:31
0
\$\begingroup\$

Possible memory leak. LibGDX uses native Box2D. To use it, they wrote Java wrapper, because of that, the objects that are created by the native methods need manual disposal.

    FixtureDef fixtureDef = new FixtureDef();
    fixtureDef.shape = shape;
    fixtureDef.density = 1f;
    Fixture fixture = body.createFixture(fixtureDef);
    shape.dispose(); // You need to dispose Shape manually...

Also do not forget to dispose the world.

@Override
public void dispose() {
    //dispose other stuff
    world.dispose();
}

Also, if more detailed profiling is not possible, comment some part and check it again ....

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.