viktov Posted June 10, 2014 Share Posted June 10, 2014 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. Quote Link to comment Share on other sites More sharing options...
Wingnut Posted June 10, 2014 Share Posted June 10, 2014 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. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted June 10, 2014 Share Posted June 10, 2014 Hello:) could you create a little playground to test your problem in live? (http://www.babylonjs.com/playground) Quote Link to comment Share on other sites More sharing options...
viktov Posted June 11, 2014 Author Share Posted June 11, 2014 Thank you guys for your response and some useful piece of knowledge Wingnut.Deltakosh, I created a simple demo for you to check and see what I mean. http://www.babylonjs.com/playground/#1WWTSA And it seems it is not only IE problem.Just run this demo, open task manager and watch for a couple of minutes how memmory grows and framerate falls. Quote Link to comment Share on other sites More sharing options...
Dad72 Posted June 11, 2014 Share Posted June 11, 2014 I do not de problem of framerate with Google Chrome and Firefox with your demo. It may be just bind a IE or not activate one option in IE ?I thought option "acceleration material", egIt's just an idea Quote Link to comment Share on other sites More sharing options...
viktov Posted June 11, 2014 Author Share Posted June 11, 2014 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. Quote Link to comment Share on other sites More sharing options...
Dad72 Posted June 11, 2014 Share Posted June 11, 2014 Ok,I'll look 15 minutes. Quote Link to comment Share on other sites More sharing options...
Dad72 Posted June 11, 2014 Share Posted June 11, 2014 No I'm still a 60 FPS. I think that's the browser or your graphics card. Quote Link to comment Share on other sites More sharing options...
viktov Posted June 11, 2014 Author Share Posted June 11, 2014 Thanks for your information. Have you looked at task manager and browser memmory usage? Quote Link to comment Share on other sites More sharing options...
Dad72 Posted June 11, 2014 Share Posted June 11, 2014 Yes, Nothing to report of my side Quote Link to comment Share on other sites More sharing options...
viktov Posted June 11, 2014 Author Share Posted June 11, 2014 http://www.babylonjs.com/playground/#1WWTSA You should see appearing and disappearing artifacts over the boxes...browser memmory raising, framerate falling down to 0...Disposed objects seem to stay somewhere there... or is it something wrong with my code? Any help would be much appreciated. Quote Link to comment Share on other sites More sharing options...
viktov Posted June 12, 2014 Author Share Posted June 12, 2014 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. Quote Link to comment Share on other sites More sharing options...
Temechon Posted June 12, 2014 Share Posted June 12, 2014 After 5 minutes, I'm at 28 FPS (started at 60 FPS), 80Mo of memory used (started at 80Mo).Edit : Windows 8.1 - Chrome last version Quote Link to comment Share on other sites More sharing options...
viktov Posted June 12, 2014 Author Share Posted June 12, 2014 Thanks Temechon.Which browser have you checked, which system you have?Im on Windows 7, IE11, FF 29.01, Chrome 35.0.1916.114.And what if you leave demo running for 20 minutes or longer? Quote Link to comment Share on other sites More sharing options...
Kilombo Posted June 12, 2014 Share Posted June 12, 2014 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? Quote Link to comment Share on other sites More sharing options...
kolar Posted June 12, 2014 Share Posted June 12, 2014 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. Quote Link to comment Share on other sites More sharing options...
Kilombo Posted June 12, 2014 Share Posted June 12, 2014 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? Quote Link to comment Share on other sites More sharing options...
viktov Posted June 12, 2014 Author Share Posted June 12, 2014 Good point, Kilombo.I have updated demo: http://www.babylonjs.com/playground/#1QA535and no doubt there is an improvement but it doesnt solve the problem.Memory grows a bit slower, but still there is +500MB in about 20 minutes using IE. Quote Link to comment Share on other sites More sharing options...
Kilombo Posted June 12, 2014 Share Posted June 12, 2014 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; } } Quote Link to comment Share on other sites More sharing options...
viktov Posted June 12, 2014 Author Share Posted June 12, 2014 Thanks Kilombo for your thoughts.I see your point. And I could do something like: http://www.babylonjs.com/playground/#QEBJSbut 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/#1KSU3XI 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. Quote Link to comment Share on other sites More sharing options...
Kilombo Posted June 12, 2014 Share Posted June 12, 2014 I just declared the var face has global, end removed it from the hidedetails and showdetails functions, and I think it sorted it out. can you check in your browser?http://www.babylonjs.com/playground/#1MBN2C#1 Quote Link to comment Share on other sites More sharing options...
viktov Posted June 13, 2014 Author Share Posted June 13, 2014 It still doesnt work for me. Windows 7, IE 11, +500MB in about 15 minutes Im running out of ideas what might be wrong with this code S.O.S. Quote Link to comment Share on other sites More sharing options...
viktov Posted June 13, 2014 Author Share Posted June 13, 2014 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); Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted June 13, 2014 Share Posted June 13, 2014 Thank you Viktov!! You found a MASSIVE memory leak with geometries! I fixed it now, you can download the latest beta:) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.