Jump to content

Problem with disposing objects


viktov
 Share

Recommended Posts

Hello everyone,

 

The project Im working on requires creating and removing certain amount of meshes at runtime.

When camera approches defined position I create, lets say, 100 meshes.

When camera moves away I dispose these meshes and materials.

 

And everything works as expected on FF and Chrome but on IE the performance decreases dramatically after creating (and disposing) few thousands meshes. IE behaves like it keeps all these objects forever, although there is no significant growth of memmory used. Scene animation gets jumpy and application becomes useless.

 

This effect is caused by the code:

function ShowHideDetails() {    for (i = 0; i < segments.length; i++) {        var segment = segments[i];        var segmentPosition = new BABYLON.Vector3(segment.x, segment.y, segment.z);                                if (!segment.isLoaded && getDistance(scene.activeCamera.position, segmentPosition) < 150) { //create objects                for (j = 0; j < segment.p.length; j++) {                    face = BABYLON.Mesh.CreatePlane("f" + segment.id + "_" + j, 1, scene);                    face.scaling.x = segment.p[j].width;                    face.scaling.y = segment.p[j].height;                    face.position.x = segment.x + segment.p[j].x + segment.p[j].width / 2;                    face.position.y = segment.p[j].y + segment.p[j].height / 2;                    face.position.z = segment.z + segment.p[j].z - 0.1;                                        var material0 = new BABYLON.StandardMaterial("m" + segment.id + "_" + j, scene);                    material0.specularColor = new BABYLON.Color3(0, 0, 0);                    face.material = material0;                }                segment.isLoaded = true;                    }        if (segment.isLoaded && getDistance(scene.activeCamera.position, segmentPosition) > 150) {  //dispose objects                        for (j = 0; j < segment.p.length; j++) {                var material = scene.getMaterialByName("m" + segment.id + "_" + j);                if (material) {                        material.dispose(true);                }                var face = scene.getMeshByID("f" + segment.id + "_" + j);                if (face) {                                       face.dispose(true);                }            }            segment.isLoaded = false;        }            }}

Am I missing something? Or should I try some other approach? Any ideas?

I'll be grateful for any suggestions.

Thanks.

 

 

Link to comment
Share on other sites

Hi Viktov, welcome to the forum... good to have you with us.  I have no definitive answers for you, but I did find this post.  I believe that the 'GCFriendlyArray' is now called 'smartArray', documented here, but I might be wrong (I often am) and this might not apply to your questions.  I think the general idea is to re-use the mesh whenever possible.

 

Other comments from smarter people than I... are sure to follow.

Link to comment
Share on other sites

dad72 - how about memmory growth? Leave it for 10 - 15 minutes and see if the framerate falls.

I have onboard graphic card which obviously is not fast, but in the begining the demo runs smoothly and after a while the performance drops dramatically.

Link to comment
Share on other sites

I think I posted wrong version of demo, thats why you did not see anything wrong going on.

I edited links above, so now you should see what the problem is.

 

Dear all,

lets find out where the problem lays because it seems quite a serious issue.

I did check in dev tools that dispose() for the mesh is called as many times as CreateBox().

It is the same with dispose() for the material.

So, one thing Im sure is that it is not the issue of dispose() not being called.

Link to comment
Share on other sites

hmmmm.. Viktov, I see you are declaring some vars inside some for scope (Ex: createsegments, showdetails and hidedetails), although the vars had the same name, and the value inside it is in fact substituted, the system will instantiate a new var in memory by each loop. And that consumes a lot of memory, and will keep growing and growing. Can you plz try do declare those vars outside of the loop scopes to see if the problem is relationed with that?

Link to comment
Share on other sites

hmmmm.. Viktov, I see you are declaring some vars inside some for scope (Ex: createsegments, showdetails and hidedetails), although the vars had the same name, and the value inside it is in fact substituted, the system will instantiate a new var in memory by each loop. And that consumes a lot of memory, and will keep growing and growing. Can you plz try do declare those vars outside of the loop scopes to see if the problem is relationed with that?

 

It's not true, read about javascript scoping and hoisting.

Link to comment
Share on other sites

It's not true, read about javascript scoping and hoisting.

Don't forget we have a render loop in here, it's not only a matter of scoping. I'm just saying that there could be a relation. I'm working on a project and had some similar problems relationed to those kind of problems. Actually I don't know enough javascipt to be sure of that. Anyway. The dispose by it self doesn't delete the actual object, just the reference to it, right? He still have to wait for the garbage collector to be cleaned. So it's not 100% sure that the dispose will take the object out of memory, right?

Link to comment
Share on other sites

Hey viktov, check this loop:

In my point of view, I think you are instantiating a new segmentPosition object by each iteration, then if not loaded it instantiates a new standard material and color3 by each iteration. By saying this it's a lot of stuff that you are instantiating, where is this all going, and how do you reference this earlier?

I f I where you, I would implement an array to put all this materials and segment positions, so that you can reference them earlier. Something like:

for (i = 0; i < segments.length; i++) {
        segment = segments;
        segmentPosition = new BABYLON.Vector3(segment.position.x, segment.position.y, segment.position.z);

And then do the same with the materials, that way you can reference them on the hide function. It looks to me that the problem is there.

Or else, you can implement some queues and them put what you whant there (on the showdetail function), and get and dispose them later (on the hide function).

 

Hope I helped something :)

for (i = 0; i < segments.length; i++) {        segment = segments[i];        segmentPosition = new BABYLON.Vector3(segment.position.x, segment.position.y, segment.position.z);                        if (!loaded[i] && i == Math.round(Math.random() * segments.length)) {            for (j = 0; j < 100; j++) {                face = BABYLON.Mesh.CreateBox("f_" + i + "_" + j, 1, scene);                face.scaling.x = Math.random() * 20 + 5;                face.scaling.y = Math.random() * 20 + 5;                face.position.x = segment.position.x + Math.random() * 50 - 25;                face.position.y = 100 + Math.random() * 50;                face.position.z = segment.position.z + Math.random() * 50 - 25;                material = new BABYLON.StandardMaterial("m_" + i + "_" + j, scene);                material.diffuseColor = new BABYLON.Color3(Math.random(), Math.random(), Math.random());                face.material = material;            }            loaded[i] = true;        }    }
Link to comment
Share on other sites

Thanks Kilombo for your thoughts.

I see your point. And I could do something like: http://www.babylonjs.com/playground/#QEBJS

but it means that I would create 10 000 meshes at once (memory peak just from the begining) and I would rather avoid this.

 

Thats why I thought that creating meshes on demand would be a solution here but I still cant get it work as it should.

Look at this:

http://www.babylonjs.com/playground/#1KSU3X

I left only meshes without any materials for the clarity of code.

I removed creation of any unneccesery objects but still there is a memory leak in this code.

Link to comment
Share on other sites

Ok, guys, I found a workaround.

If I clone meshes and materials instead of creating new instaces each time, it works fine.

Although it still doesnt explain the memory leak when creating - disposing meshes.

So for now, it solves the problem for me, but if somebody would take a deeper look into it to make sure there is no bug in the framework, that could be helpful.

 

Here's working code:

var segments = [];var loaded = [];var cube = new BABYLON.Mesh.CreateBox("cube", 1, scene);var baseMaterial = new BABYLON.StandardMaterial("baseMaterial", scene);function createGround() {    var groundMaterial = new BABYLON.StandardMaterial("groundMaterial", scene);    var ground = BABYLON.Mesh.CreateGround("ground", 1000, 1000, 1, scene, false);    groundMaterial.diffuseColor = new BABYLON.Color3(0.0, 0, 0.5);    ground.material = groundMaterial;    ground.checkCollisions = true;}function createCamera() {    var freeCamera = new BABYLON.FreeCamera("freeCamera", new BABYLON.Vector3(0, 150, -500), scene);    freeCamera.maxZ = 2000;    freeCamera.applyGravity = true;    freeCamera.ellipsoid = new BABYLON.Vector3(40, 75, 20);    freeCamera.position = new BABYLON.Vector3(0,150,-800);    freeCamera.speed = 8;    return freeCamera;}function createSegments(){    var segment;    var material;    for(i = 0; i < 50; i++) {        segment = cube.clone("segment" + i);        segment.scaling = new BABYLON.Vector3(50,50,50);        segment.position = new BABYLON.Vector3(Math.random() * 1000 - 500, 25, Math.random() * 1000 - 500);        material = baseMaterial.clone("segmentMaterial" + i);        material.diffuseColor = new BABYLON.Color3(Math.random(), Math.random(), Math.random());        segment.material = material;        segments.push(segment);        loaded.push(false);    }}function ShowDetails() {    var face;    var material;    for (i = 0; i < segments.length; i++) {        if (!loaded[i] && i == Math.round(Math.random() * segments.length)) {            for (j = 0; j < 100; j++) {                face = cube.clone("f_" + i + "_" + j);                face.id = "f_" + i + "_" + j;                face.scaling.x = Math.random() * 20 + 5;                face.scaling.y = Math.random() * 20 + 5;                face.position.x = segments[i].position.x + Math.random() * 50 - 25;                face.position.y = 100 + Math.random() * 50;                face.position.z = segments[i].position.z + Math.random() * 50 - 25;                material = baseMaterial.clone("m_" + i + "_" + j);                material.diffuseColor = new BABYLON.Color3(Math.random(), Math.random(), Math.random());                face.material = material;            }            loaded[i] = true;        }    }}function HideDetails(){    var face;    var material;    for (i = 0; i < segments.length; i++) {        if (loaded[i]) {            for (j = 0; j < 100; j++) {                material = scene.getMaterialByName("m_" + i + "_" + j);                if (material) {                    material.dispose();                }                face = scene.getMeshByID("f_" + i + "_" + j);                if (face) {                    face.dispose();                }            }            loaded[i] = false;        }            }}createGround();createSegments();var camera = createCamera();camera.attachControl(canvas, false);var light = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0), scene);setInterval(function () { ShowDetails(); }, 500);setInterval(function () { HideDetails(); }, 2000);
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...