7

my application loads a lot of meshes. to get rid of old meshes i try to dispose them. but the memory is never being freed.

am i missing something ?

my simple example for reproducing:

  1. load 100 of big binary meshes
  2. dispose all of them again
  3. chrome task manager says 250mb memory used, its exactly the same as without step 2

    memtest

    var scene = new THREE.Scene();
    var mymesh=Array();
    
    // 1. load a lot of geometry/meshes...
    
    for(var i=0;i<100;i++)
    {
        var bloader;
        bloader = new THREE.BinaryLoader();
    
        bloader.load( "objekte/presto_6.js" , function( geometry ) 
        {
            mymesh.push(new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( {color:0xffffff } ) ));
            scene.add(mymesh.length-1);
        });
    }
    
    // 2. try to dispose objects and free memory...
    
    for(var j=0;j<mymesh.length;j++)
    {
        mymesh[j].geometry.dispose();
        mymesh[j].material.dispose();
        screne.remove(mymesh[j]);
    }
    
    mymesh=Array();
    
    </script>
    

seattledirk
  • 123
  • 1
  • 1
  • 6

1 Answers1

10

Probably a typo, but if it isn't: screne.remove(mymesh[j]); should be scene.remove(mymesh[j]);

Other than that: rember (or find out) how JS manages the memory. Its garbage collector is a sweep-and-clean GC. It flags objects that aren't being referenced anywhere and then cleans them next time the GC kicks in:

for(var j=0;j<mymesh.length;j++)
{
    mymesh[j].geometry.dispose();
    mymesh[j].material.dispose();
    scene.remove(mymesh[j]);
}

The mymesh array still contains references to the mesh objects you are attemting to free. The GC sees this referenec, and therefore refrains from flagging these objects. Reassign, delete, either the entire array of those specific keys you no longer need:

for(var j=0;j<mymesh.length;j++)
{
    mymesh[j].geometry.dispose();
    mymesh[j].material.dispose();//don't know if you need these, even
    scene.remove(mymesh[j]);
    mymesh[j] = undefined;//or
    delete(mymesh[j]);
}
//or simply:
mymesh = undefined;//or some other value

That allows the memory to be freed, unless another variable remains in scope that references some or all of these objects, too.
As an asside:

mymesh=Array();

Is bad code on many levels. JS functions that begin with an UpperCase are constructors, and should be called usign the new keyword, though most constructors (especially the native objects) shoul be called as little as possibe.
Their behaviour can be unpredictable, and there's often a shorter way to write the code:

mymesh = [];//an array literal
//example of werird behaviour:
mymesh = new Array(10);//[undefined, undefined, undefined....]
mymesh = [10];
mymesh = new Array('10');//['10']
mymesh = new Array(1.2);//RangeError
var o = new Object(123);//returns new Nuber
o = new Object('something');//new String
o = new Object(false);//new Boolean
o = new Object('foo', 'bar');//new String('foo')!!!
o = {foo: 'bar'};//<-- this is soooo much easier
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
  • 1
    my next question would be if it is possible to just delete the data of vertices/faces/normals etc when it was uploaded to the gpu. i know there is geometry.dynamic=false; but the vertices data is still there i believe. can i free that memory too ? if i try something like "zmesh.geometry.vertices = undefined;" threejs cannot access .length of this array. – seattledirk Feb 18 '14 at 11:11
  • @pandrr: Of course, if you assign `undefined` to something that is then used as an array, you're effectively doing `undefined.length`, which is impossible. You could try `zmesh.geometry.vertices = []`. Howeve: JS is Garbage Collected: you have _no real control_ over the memory. If you want to manage every byte of memory yourself, you'll have to write C :) A simple thing you can do to help the GC is _not_ to use the global scope, just write `(function(){` on the first line of your script, and add `}());` at the end, and _declare every var_ – Elias Van Ootegem Feb 18 '14 at 11:14
  • sure its logical that this does not work. it was more of a threejs question, if it is possible to release that data, because it was already stored on the gpu and will not be changed, so no need to access it again. – seattledirk Feb 18 '14 at 11:19
  • 1
    @seattledirk: Not sure about that, I'm inclined to say no, it isn't possible. Owing to the fact that JS is a high-level language, you have no real say in memory management: If the data is stored on the GPU, the thread running your code manages the resources, not your code. That thread will still retain the data in some way or another. If you were to truly free the memory, the kernel would be free to use the memory that holds your data, so it might be overwritten 2ms further down the line. – Elias Van Ootegem Feb 18 '14 at 11:51