vasturiano / 3d-force-graph

3D force-directed graph component using ThreeJS/WebGL
https://vasturiano.github.io/3d-force-graph/example/large-graph/
MIT License
4.8k stars 831 forks source link

Memory issue associated with nodeThreeObject #202

Open guangyan-zhou opened 5 years ago

guangyan-zhou commented 5 years ago

Hello All,

I am aware there is a previous thread about the memory issue with nodeThreeObject. I am wondering if there is any updates to this problem? As for me, everytime I repopulate the network (add, remove nodes, load a different network), the memory increases by ~60 mb (~800 nodes, ~1000 links). But if I remove nodeThreeObject option, the memory stays constant after graph modifications.

Thank you, Guangyan

vasturiano commented 5 years ago

Hi @zzggyy1, thanks for reaching out. Complete memory cleanup remains a bit of a challenge, but with regular objects it seems to perform acceptably at the moment. Here is the current cleanup method for each object: https://github.com/vasturiano/three-forcegraph/blob/master/src/forcegraph-kapsule.js#L460

It basically runs recursively through each object's geometry, material and texture and disposes them.

Could you post your nodeThreeObject method to see if there's something there that's not being properly deallocated. Also, could you find a simplified version of it that does not cause the memory leak, to try and isolate the issue?

413x-p commented 5 years ago

Hi, i am not sure how can i use forcegraph-kapsule.js to clear the entire scene. I have tried some several three.js methods but without any success.

I am trying to make a chart to work without a page refresh, the only problem is that the GPU ram is filling with each new data that i introduce into the chart even if the old data is not appearing anywhere. I have to make a chart that will get new data and it will dispose of the old data automatically each 10 seconds. Is there a way to remove all the geometries/textures/etc that are not used in the scene? with three.js i have tried to use a "dispose" method but it is undefined. Most probably this is a three.js issue but i am not sure how to access the geometries/texture/etc that have to be removed when i use 3D Force Graph.

Any tips?

Thank you.

413x-p commented 5 years ago

To be more exactly, in three.js rendeder.renderLists.dispose(); should clear the memory but when i use it for 3D Force Graph like this Graph.renderer().renderLists.dispose(); i get a undefined.

And i have tried this:

    jsonServitX = {
        "nodes": [{ "id": "Causations", "color": "#fefc54", "NewsIPv6s": ["2a02:2a00:cc00:16::2d4:bc86", "2a02:2a00:cc00:16::2e1:c532"] }],
        "links": []
    }
    jsonServit = {
        "nodes": [{ "id": "Causations", "color": "#fefc54", "NewsIPv6s": ["2a02:2a00:cc00:16::2d4:bc86", "2a02:2a00:cc00:16::2e1:c532"] }],
        "links": []
    }

    Graph.graphData({
        "nodes": [{ "id": "Causations", "color": "#fefc54", "NewsIPv6s": ["2a02:2a00:cc00:16::2d4:bc86", "2a02:2a00:cc00:16::2e1:c532"] }],
        "links": []
    });

    setTimeout(function () {
        const cleanMaterial = material => {
            console.log('dispose material!')
            material.dispose()

            for (const key of Object.keys(material)) {
                const value = material[key]
                if (value && typeof value === 'object' && 'minFilter' in value) {
                    console.log('dispose texture!')
                    value.dispose()
                }
            }
        }

        Graph.scene().traverse(object => {

            console.log(object);

            if (!object.isMesh) return

            //console.log('dispose geometry!');
            object.geometry.dispose()

            if (object.material.isMaterial) {
                cleanMaterial(object.material)
            } else {
                // an array of materials
                for (const material of object.material) cleanMaterial(material)
            }
        })
    }, 2000);

    Graph.renderer().dispose();
    Graph.renderer().forceContextLoss();
    Graph.renderer().context = undefined;
    Graph.renderer().domElement = undefined;

    Graph.scene().dispose();

    $("#x3d-graph").empty();

I am sure that i am missing something, the code runes without error but it doesnt free enough VRAM.

Thanks