Nodragem

How to restart a level (dispose of previous one) without memory leak?

Recommended Posts

Hello,

I created a game state GameplayLoop that is made of a scene and a UI root, and I restart my GameplayLoop with a new level when my player reaches a specific score.

When I restart my game state, I dispose of my scene and UI and I reload everything (except text-based data) relying on the engine caching for not reloading texture that already exist. (Note that I reload the same texture right now).

 

However, doing so decreases the framerate and increases the memory usage each time I restart the GameplayLoop.

I found that I could dispose the engine and recreate a new engine in order to get rid of this memory leak ... is that the actual way to do it?

 

EDIT: the main issue with disposing of the engine is that this also disposes of the other scenes that I would have liked to display after/during the GameplayLoop.

Share this post


Link to post
Share on other sites

Sorry to double-post, the forum is often very active hence I start to think that I did not get answers yet maybe because I did not explain my problem very well?

 

Basically, I have an object which load/create a Scene and a BABYLON.GUI.AdvancedDynamicTexture (the UI root). I call that object a Game State in my previous post.

I would like to dispose of my object so that I can reload it from scratch.

When I do Scene.dispose() and BABYLON.GUI.AdvancedDynamicTexture.dispose() it seems that this is not enough to clean-up all my mess.

In fact, when I reload/create the Scene and UI, ; and I get more memory and CPU usage than on the first creation of my Game State...

 

Any thought on what else than scene.dispose() and ui.dispose() I should do in order to clean-up  my BABYLON.engine without disposing of my BABYLON.engine?

Share this post


Link to post
Share on other sites

Ideally I would like not to dispose of my engine, I would prefer to clean it up.

I think the increase of CPU usage each time I reload a level may be due to callbacks not being cleaned up. For instance many objects register to registerBeforeRender(). Do I need to unregister them before to dispose of the scene?

Share this post


Link to post
Share on other sites

Hello, 

I made some screenshot of the performance profiler in order to help you to help me :) !

So basically, I am reloading my level every 5 second and I used Opera's profiler to record what's happening (which is basically Chrome's profiler).

opera_2018-11-18_10-38-42.thumb.png.0ceb5ffc6ca3779d6abf7bc82dbfef7a.png

So yes, my game is not optimised yet, so the CPU is highly used to animate and render hundreds of objects (I am planing to merge my static objects into one mesh, and use Solid Particles for the dynamic one, but that's another story).

What worries me is that the FPS decreases and the memory usage increases every time that the level is reloaded:

opera_2018-11-18_10-39-08.png.f3e7a480e62d00f8081fdbe0d935f407.png

I also now noticed the appearance of this red bar in the profiler, when the level is loaded for the 3rd time:

opera_2018-11-18_10-39-33.png.4042e09074d6b1fcc25d71cbbdd00e0f.png

Another interesting fact is that the CPU has a usage drop during the loading screen (sounds about right!, see 16000ms and 34000ms) but not always (note how the CPU do not decrease on the second loading screen, 24000ms):

image.png.dc98940c82817be071127885ff73fbf0.png

 

There is clearly things that are not clean-up with scene.dispose() and these remains are accumulating into a huge drop in performance. I could believe that these remains are not BABYLONJS-related, however, the fact that to simply use engine.dispose() resolve the troubles; I am inclined to think that these remains are BABYLONJS-related. Does that sound like a reasonable conclusion @Deltakosh ?

Are there any other functions than scene.dispose() that I should call to clean-up my engine before to reload a level?

 

From what  I found on the topic, scene.dispose() should be enough:

http://www.html5gamedevs.com/topic/27615-proper-way-to-clear-entire-scene/

http://www.html5gamedevs.com/topic/31160-scene-cleaning-problem/

http://www.html5gamedevs.com/topic/22211-how-to-destroy-scenes/

engine.dispose() should only be used if we want to get rid of cached textures and assets; which I don't want to get rid of as I am reusing the same assets on the next levels.

 

... :( I mean for now, I am kind of forced to use engine.dispose(); but hopefully I will finally understand what's going wrong with my scene disposal. I am going to try un-registering my beforeRender callback now.

 

 

Share this post


Link to post
Share on other sites

I am not very familiar with profilers. It's something I'm going to have to learn to use a day.

Me when I have a scene, I also reset the variables, especially arrays, and I put the scene variable to null too.

But maybe there is something not clean with scene.dispose (). Deltakosh will be able to check it, but there he is on vacation for 15 days.

Sorry for not being able to help anymore. I hope someone can better understand your problem than me.

Share this post


Link to post
Share on other sites

I am also discovering the profiler to be honest :) I am quite new to web development.

I will try setting the scene variable to null. Although, if I remember well, my scene variable is re-attributed to a new scene, so the old one should become a "dead memory space"  and be collected by the garbage collector. I do have a lot of arrays too I believe, but again, they are re-attributed to new ones when the level restarts, so I would think the old ones get cleaned by the garbage collector...

In fact, that does not seem to come from my arrays because engine.dispose() resolves my troubles; but I may need to double-check; there must be something that the engine remembers and that can't be collected by the garbage collector.

Thank for the help, this is very much appreciated :) hope Deltakosh is having a good rest!

Share this post


Link to post
Share on other sites

@Nodragem this looks like a nice memory leak (I say nice cause it is big enough to see on a small number of restart which might help troubleshooting).

The way I usually go with those is in the chrome dev tools. If you go in the memory profiler and by comparing snapshots. 

What i would do in your case is force reloading the same level instead of a different one and compare the memory napshots before and after reload to identify the newly created objects.

Hope that might help. If you can repro in the playground I ll definitely give it a shot ASAP.

Share this post


Link to post
Share on other sites

In fact, I am reloading the same level; using the same assets. That's just that it is a procedurally generated maze; so it may look different each time.

Concerning reproducing it in PG, I will try to, but not sure I will have time before Thursday.

Share this post


Link to post
Share on other sites

Oh if it is procedurally generated, comparing memory might not help as much so it might be a bit harder to track down the culprit. A playground would be the best to isolate the none released objects and figure out where does the leak come from?

Share this post


Link to post
Share on other sites

so yeah, to make a PG example is a bit complicated because I basically need a lot of my functions/objects/textures/assets to run the example.

Hence, instead I made a branch on Bitbucket that you can clone, but I can not share it publicly, so you would need to PM me if you're interested in having a look (yeah, I am decreasing all my chances to be helped! sorry 😕 ).

By the way, I realised that last time, I had the inspector opened! hence that may be why the CPU was bloated!

 

I re-run my test without the inspector (and some optimisation using mergeMeshes() / SPS), that works much better in term of CPU, but we can still see a leak after few scene reload.

Here the first few scene reloads. You can see that the CPU is at 100% when I load the maze, then the processor relaxes during the game (yellow curve in the top graph), the FPS is at 0 during the loading time (cause 1 static image) and ~60 during the game (the green curve in the top graph).

opera_2018-12-13_14-53-06.thumb.png.8056e0c6ec2a62cdc859cc692aa51de5.png

After a few scene reloads, I recorded again. You can see that the CPU does not relaxes as well as before during the game (yellow curve in the top graph), the FPS drop at  ~50 during the game (the green curve in the top graph).

opera_2018-12-13_14-55-11.thumb.png.abc34cec00a0897c95708055cecea0dd.png

 

Any thoughts?

I would like to ping @Deltakosh on that one, cause they were in holidays at the time I started the thread :) 

Also, in term of the new forum, should I do anything to redirect this thread to the new forum? Thanks for your help !

Share this post


Link to post
Share on other sites
45 minutes ago, Nodragem said:

Also, in term of the new forum, should I do anything to redirect this thread to the new forum? Thanks for your help !

You must recreate it to continue the discussions on the new forum.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.