On an application I am working that does a lot of remote loading and creating new entities that replace the previous on runtime I noticed a memory leak. The JS heap is continuously increasing.
I isolated the issue on the code that creates the new batch of entities. I made sure that I remove all created entities before I initiate a new creative cycle using something like this:
for (i = this.holderEntity.children.length - 1; i >= 0; --i) {
if( this.holderEntity.children[i] instanceof pc.Entity ){
this.holderEntity.children[i].destroy();
}
}
I check that the holderEntity is empty before adding new ones and it is. But the memory leak is still in place, like additional entities are added and previous arenât completely destroyed.
I created a separate array and pushing in there the all entities added and - just to be sure - I destroy all entities in there as well:
for (i = this.deleteArray.length - 1; i >= 0; --i) {
this.deleteArray[i].destroy();
}
When inspecting this array I see that entities arenât destroyed on first block code, but only removed from holder entity. And still, the destroy() method doesnât completely destroy them, entities are still there referenced by the deleteArray.
I tried event using the delete keyword:
for (i = this.deleteArray.length - 1; i >= 0; --i) {
delete this.deleteArray[i];
}
I am feeling stuck here, any ideas? I reproduced the case in this project:
https://playcanvas.com/editor/scene/490286
Code on third script that clones entities on intervals and removing them:
var Test = pc.createScript('test');
// initialize code called once per entity
Test.prototype.initialize = function() {
this.test = Array();
this.bank = this.app.root.findByName('Test');
this.children = this.app.root.findByName('Children');
window.setInterval(function(){
for (i = 0; i < 1000; i++) {
var child = this.bank.clone();
child.name = 'Name'+this.test.length;
this.children.addChild(child);
this.test.push(child);
}
for (i = this.children.children.length - 1; i >= 0; --i) {
if( this.children.children[i] instanceof pc.Entity ){
this.children.children[i].destroy();
}
}
console.log(this.test);
}.bind(this), 3000);
};