How does babylon free up memory quickly when a page is unloaded

I write a simple page to test Garbage Collection.
Monitor performance panel data changes by repeatedly adding and removing IFrames

  • iframe page content
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #view3d {
        width: 100%;
        height: 100%;
        overflow: hidden;
        position: relative;
      }
    </style>
  </head>
  <body>
    <canvas id="view3d"></canvas>
  </body>
  <!-- <script src="./babylon.js"></script> -->
</html>

A minute after removing the iframe page, the internal dom still hasn’t been freed


  • iframe page content
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #view3d {
        width: 100%;
        height: 100%;
        overflow: hidden;
        position: relative;
      }
    </style>
  </head>
  <body>
    <canvas id="view3d"></canvas>
  </body>
  <script src="./babylon.js"></script>
</html>


15 seconds after removing the iframe page, the internal dom is released


Therefore, I think babylon did some processing before unloading the page;
Then I went to babylon’s code and found this:

At this point, I think babylon manually destroyed the canvas element to avoid memory leaks


I tried to do the test in the same way:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #view3d {
        width: 100%;
        height: 100%;
        overflow: hidden;
        position: relative;
      }
    </style>
  </head>
  <body>
    <div id="view3d"></div>
  </body>

  <script type="module">
    var fn = () => {
      let dom = document.querySelector("#view3d");
      const parentControl = dom.parentElement;
      parentControl.removeChild(dom);
      dom = null;
    };
    window.addEventListener("beforeunload", fn);
  </script>
</html>

It did not have the desired effect and the dom was not destroyed


Maybe I’m looking in the wrong place
Maybe someone can show me the right way to destroy the dom and achieve memory reclamation
Thanks !!!

AFAIK, when a page is unloaded, all elements are automatically retrieved by the browser, so you don’t even need to free/delete them from the DOM. However, the browser can run the garbage collector at any time, so it doesn’t need to retrieve memory only at unload time. In your test, try forcing a garbage collect and see if it helps (in the “Performance” tab, there’s a garbage can icon that lets you do a manual garbage collect).

You can’t directly free-up DOM GC but you can help memory management with removing references and objects, which may result in faster GC. If you’re removing <iframe> elements then you’re doing all that’s required for GC. It may be taking 15 seconds because the browser is utilising thread memory bandwidth to keep a smooth browser experience; it may also be considering to keep resources in memory if you re-visit any resources in a short time, which can be likely if a user “re-opens” a tab (this is my conjecture). Also note experience will differ across browsers.

If you’re re-creating <iframe> elements in a short amount of time then I would imagine you may eventually get performance/memory heap spikes. Also DOM Renderers can be shared across <iframe>'s if the same browser tab + domain, thus could hold-up its parent and children trees rendering. I have a feeling Facebook may be taking advantage of this as they like to use <iframe>s.

I would ignore DOM GC and concentrate on JS GC for Babylon testing. Store the <canvas> and engine refs in a top-level state class and any app related variables (as const or let) here too. Also any DOM elements you may create you will want to manage them here too because any references to these can prevent GC. You may create a function in the class to null/clear variables as required.

3 Likes

@Evgeni_Popov @j-te
So maybe my test results were just a fluke?
Let me mistakenly think babylon has some dark technology to speed up garbage collection

This is a good way to prevent memory leaks

No, Babylon does not do any black magic regarding the garbage collection process :slight_smile:

Babylon does white magic only :sunglasses:
Gandalf GIF - Find & Share on GIPHY | Lord of the rings, Gandalf the white, Gandalf