Memory leak after adding/removing BufferGeometries multiple times

Hello!
Finally, I reached a level of the functionality of my application.
But the performance is super bad.
I am adding line cubes to a scene, creating a grid. When I change the dimensions of the cube and the number of rows and columns I remove all cubes and create a new grid.
Not the most elegant way, but it worked so far.
For the first 2 to 3 changes, everthing runs smoothly but then the performance drops.

I tried to clean the scene manually be looping over the children of the geometry groups and dispose their geometry. But this didn’t do the trick.

Here is an example of the initial code. Should give you an idea of my concept:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 5, -1000);
var renderer = new THREE.WebGLRenderer({
 antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var dimensions = {
   "w": 2,
 "h": 1,
 "l": 3,
 "Woff": 0.5,
 "Loff": 1,
 "row":1,
 "col": 2
}

var addButton = document.createElement("button");

addButton.innerHTML="Add+1"
addButton.onClick = function(){
dimensions.w=dimensions.w+1;
dimensions.l=dimensions.l+1;
updateCubes()
cubeCluster()
}

cubeCluster()

var controls = new THREE.OrbitControls(camera, renderer.domElement);

function cubeCluster(){
   for (let ir=0; ir<dimensions.row;ir++){
 	for(let jc=0;jc<dimensions.col;jc++){
   	createCube(dimensions.w, dimensions.h, dimensions.l, jc, ir, dimensions.Woff, dimensions.Loff)
    }
 }
}


function createCube(w, h, l, c, r, Woff, Loff) {
                       // BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)
                       let cubeGeometry = new THREE.BoxBufferGeometry(w, h, l);
                       let edges = new THREE.EdgesGeometry( cubeGeometry );
                       let lineBox = new THREE.LineSegments( 
                       	edges, new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 0.5 } ) 
                       );

function removeEntity(object) {
   let selectedObject = scene.getObjectByName(object);
            
       for (let i in selectedObject.children) {
           selectedObject.children[i].geometry.dispose()
           selectedObject.remove(selectedObject.children[i]);
         }
       scene.remove( selectedObject );
   animate();
}

function updateSplit(){
                       let ubList=[];
                       for(let q in scene.children){
                           if(scene.children[q].name.match(/UnitBox/)){
                              ubList.push(scene.children[q].name)
                           }
                       }
                       for(let sc of ubList){
                           removeEntity(sc);
                       }
}

I’m really thankfull for some advices.

Cheers!

Stefan

Can you also show how you remove the cubes from the scene and dispose the respective geometry?

BTW: There is no need to create an instance of LineBasicMaterial in createCube() every time. Instead, create a material once outside of the function and reuse it for all upcoming line segments.

Thanks! For the fast response.
Indeed! I haven’t thought about this. Thanks for the hint.

I updated the my example with the function to remove the cubes.

Cheers!

Okay, you properly dispose your geometries :+1:

I think i can only provide more help if you create a live example that illustrates the performance problem.

Maybe on more hint: If this geometry (i mean edges) is equal for all cubes of a cluster, you should define it in cubeCluster() once and pass it as an argument to createCube().

Thanks! This helped a bit. I found out, that the CPU gets up to 100% over time. As a solution the merging of the single Objects into one geometry might help.
I gonna try this.

Struggeling with the merge process.
The result of createCube() is a BufferGeometry. A THREE.Geometry (ClusterGeometry) does not accept the BufferGeometry for the merge. I tried different approaches. Does the ClusterGeometry need to be an BufferGeometry too?

Cheers,

Stefan

Why do you work with THREE.Geometry? According to your code, you only use BufferGeometry, right?

Like i said before, providing a live demo makes it easier to understand your issue.

All right!
Sorry for the delay!
So here a working example. Its not super elegant, but it does the trick:
I updated the example. Should work now.

example

Thanks, for the help!!

Cheers,

Stefan

I tried also a different approach, which I found in a forum.
In each loop cycle I just I translate the edgesGeometry and merge it then to a Cluster. Afterwards, I feed this geometry together with the material into a THREE.LineSegment.
I still try searching for the right approach.
Thanks in advance!!

Cheers Stefan

Okay, i’ve updated your example with my previous suggestion: https://jsfiddle.net/f2Lommf5/3514/

I also removed some unnecessary calls of animate(). These calls were also not good for the performance of the app…

Merging the geometries to reduce the amount of draw calls would be the next step :+1:

Awesome!!! Really nice to see how it has to be done :slight_smile:
Thanks a lot for the support!!

Cheers Stefan