Memory leak issue

I’m loading different types of animals in my scene. When I leave the page I want to dispose all the animals.

I try to do that with this code:

animals.forEach((animal) => {
        scene.remove(animal);
        disposeHierarchy(animal, disposeNode);
      });

function disposeHierarchy(node, callback) {
  for (var i = node.children.length - 1; i >= 0; i--) {
    var child = node.children[i];
    disposeHierarchy(child, callback);
    callback(child);
  }
}

function disposeNode(node) {
  if (node instanceof THREE.Mesh) {
    if (node.geometry) {
      node.geometry.dispose();
    }
  if (node.material) {
    if (node.material instanceof THREE.MeshFaceMaterial) {
      node.forEach(node.material.materials, function (idx, mtrl) {
        if (mtrl.map) mtrl.map.dispose();
        if (mtrl.lightMap) mtrl.lightMap.dispose();
        if (mtrl.bumpMap) mtrl.bumpMap.dispose();
        if (mtrl.normalMap) mtrl.normalMap.dispose();
        if (mtrl.specularMap) mtrl.specularMap.dispose();
        if (mtrl.envMap) mtrl.envMap.dispose();
        if (mtrl.alphaMap) mtrl.alphaMap.dispose();
        if (mtrl.aoMap) mtrl.aoMap.dispose();
        if (mtrl.displacementMap) mtrl.displacementMap.dispose();
        if (mtrl.emissiveMap) mtrl.emissiveMap.dispose();
        if (mtrl.gradientMap) mtrl.gradientMap.dispose();
        if (mtrl.metalnessMap) mtrl.metalnessMap.dispose();
        if (mtrl.roughnessMap) mtrl.roughnessMap.dispose();
        mtrl.dispose(); // disposes any programs associated with the material
      });
    } else {
      node.material.forEach((material) => {
        if (material.map) material.map.dispose();
        if (material.lightMap) material.lightMap.dispose();
        if (material.bumpMap) material.bumpMap.dispose();
        if (material.normalMap) material.normalMap.dispose();
        if (material.specularMap) material.specularMap.dispose();
        if (material.envMap) material.envMap.dispose();
        if (material.alphaMap) material.alphaMap.dispose();
        if (material.aoMap) material.aoMap.dispose();
        if (material.displacementMap) material.displacementMap.dispose();
        if (material.emissiveMap) material.emissiveMap.dispose();
        if (material.gradientMap) material.gradientMap.dispose();
        if (material.metalnessMap) material.metalnessMap.dispose();
        if (material.roughnessMap) material.roughnessMap.dispose();
        material.dispose();
      });
    }
  }
}
  } 

However I still have a memory leak when I look in my dev tools… see image

Try with function like this…

function disposeNode (node)
{
    if (node instanceof THREE.Mesh)
    {
        if (node.geometry)
        {
            node.geometry.dispose ();
        }

        if (node.material)
        {
            if (node.material instanceof THREE.MeshFaceMaterial)
            {
                $.each (node.material.materials, function (idx, mtrl)
                {
                    if (mtrl.map)               mtrl.map.dispose ();
                    if (mtrl.lightMap)          mtrl.lightMap.dispose ();
                    if (mtrl.bumpMap)           mtrl.bumpMap.dispose ();
                    if (mtrl.normalMap)         mtrl.normalMap.dispose ();
                    if (mtrl.specularMap)       mtrl.specularMap.dispose ();
                    if (mtrl.envMap)            mtrl.envMap.dispose ();
                    if (mtrl.alphaMap)          mtrl.alphaMap.dispose();
                    if (mtrl.aoMap)             mtrl.aoMap.dispose();
                    if (mtrl.displacementMap)   mtrl.displacementMap.dispose();
                    if (mtrl.emissiveMap)       mtrl.emissiveMap.dispose();
                    if (mtrl.gradientMap)       mtrl.gradientMap.dispose();
                    if (mtrl.metalnessMap)      mtrl.metalnessMap.dispose();
                    if (mtrl.roughnessMap)      mtrl.roughnessMap.dispose();

                    mtrl.dispose ();    // disposes any programs associated with the material
                });
            }
            else
            {
                if (node.material.map)              node.material.map.dispose ();
                if (node.material.lightMap)         node.material.lightMap.dispose ();
                if (node.material.bumpMap)          node.material.bumpMap.dispose ();
                if (node.material.normalMap)        node.material.normalMap.dispose ();
                if (node.material.specularMap)      node.material.specularMap.dispose ();
                if (node.material.envMap)           node.material.envMap.dispose ();
                if (node.material.alphaMap)         node.material.alphaMap.dispose();
                if (node.material.aoMap)            node.material.aoMap.dispose();
                if (node.material.displacementMap)  node.material.displacementMap.dispose();
                if (node.material.emissiveMap)      node.material.emissiveMap.dispose();
                if (node.material.gradientMap)      node.material.gradientMap.dispose();
                if (node.material.metalnessMap)     node.material.metalnessMap.dispose();
                if (node.material.roughnessMap)     node.material.roughnessMap.dispose();

                node.material.dispose ();   // disposes any programs associated with the material
            }
        }
    }
}   // disposeNode

function disposeHierarchy (node, callback)
{
    for (var i = node.children.length - 1; i >= 0; i--)
    {
        var child = node.children[i];
        disposeHierarchy (child, callback);
        callback (child);
    }
}

And then call the function with this…

disposeHierarchy (model, disposeNode);
2 Likes

hi,

sorry for the dummie question. When could be invoked this function?

when is out the scene, or at moment in loading all objects?

best regards

if you have the main function anywhere in you code, you can invoke it at any time using…

scene.remove(YourModel)
disposeHierarchy (YourModel, disposeNode);

then

scene.add(yourNewModel1)

but yes, remove your model from scene first, invoke this function and then add new models…

hope that makes sense?

Great i got it

although coming from aframe js code, with loading of entities of the style

<a-scene arjs = “debugUIEnabled: false”
<a-marker
<a-entity id = “entity001” …>
<a-entity id = “entity002” …>
<a-entity id = “entity003” …>
<a-entity id = “entity004” …>
<a-entity id = “entity005” …>


How could I add and remove them programmatically?

thanks for your help, you are the master!

In a frame I think it is called garbage collect or “gc.collect” , but I don’t really know a frame so not sure