Bug : Entity.parent and _children relation may cause memory leak + an exception is thrown...

I’ve noticed a memory leak when removing an entity that as a parent. And there’s an exception when trying to set the Entity’s parent to undefined

Currently in my Cesium app I am grouping entities together by settings their ‘parent’ entity to a dummy entity. When I remove a child entity, it is still exists in the parent’s _children array. This causes a memory leak, since these

removed children are still retained by the parent’s _children array. I have tried to get the child and set it’s parent to undefined, but this caused an exception - look at the code below for better explanation.

What I would expect is when I remove an entity that has a parent, it would automatically remove it from the parent’s _children array, but I can manage doing this by myself when that ‘undefined’ bug is gone.

Code to reproduce:

var viewer = new Cesium.Viewer(‘cesiumContainer’);

// An entity to serve as a parent to many entities

var groupEntity = viewer.entities.getOrCreateEntity(‘myGroup’);

// An example for a child entity

var ent1 = viewer.entities.add({

id : ‘dummy1’,

polyline : {

positions : Cesium.Cartesian3.fromDegreesArray([-75, 35,

-125, 35]),

width : 5,

material : Cesium.Color.RED

}

});

// Set the relation to the group entity

ent1.parent = groupEntity;

// Expected to be 1, and it is 1

console.log('expected to be 1 and it is ', groupEntity._children.length);

viewer.entities.remove(ent1);

// Expect to be 0 but still 1

console.log('expected to be 0 and it is ’ groupEntity._children.length);

// So, now I attempt to fix - and it throws exception

// since you can’t set a parent to null but only to another ent

ent1.parent = undefined;

``

Entity.js line 286 - Code in yellow throws exception, code in pale-orange - not the best perfomance (o[n] search).

parent : {
get : function() {
return this._parent;
},
set : function(value) {
var oldValue = this._parent;

            if (oldValue === value) {
                    return;
            }

            var wasShowing = this.isShowing;
            if (defined(oldValue)) {
                    var index = oldValue._children.indexOf(this);
                    oldValue._children.splice(index, 1);
            }

            this._parent = value;
            value._children.push(this);

            var isShowing = this.isShowing;

            if (wasShowing !== isShowing) {
                    updateShow(this, this._children, isShowing);
            }

            this._definitionChanged.raiseEvent(this, 'parent', value, oldValue);
    }

},

``

Currently as a workaround I have done this :

var index = ent1.parent._children.indexOf(ent1);

ent1.parent._children.splice(index,1);

viewer.entities.remove(ent1);

``

Anyway, I plan to abandon the Entity API in favor of primitives since I need to use GroundPrimitives. When I’ll do that I’ll manage my ‘entity groups’ as primitive collections

Thanks for the bug report. Manually setting entity.parent to undefined is supposed to work. I just opened a pull request to fix the exception: https://github.com/AnalyticalGraphicsInc/cesium/pull/3169

You are mistaken that calling viewer.entities.remove(ent1); should set ent1.parent to undefined, however. The presence of an entity in an EntityCollection has no impact on who it’s parents or children are.

Hey Matthew

Thanks for clarifying about the parent-children relation.

In my case, I had hundreds of entities added and removed each few seconds from an EntityCollection for a single parent (some load tests we were running). The _children array would keep growing until the the chrome tab was choking after reaching huge memory usage.

Hi Matthew,
I’ve came across this same problem lately. I’m handling a relatively big data set on Cesium with a very high change rate.

Wouldn’t it be better to handle this while removing an entity from the collection, we could do something like in EntityCollection.removeById:

if (defined(entity.parent)){
// remove the child from from the entity.parent._children
entity.parent._children.remove(entity.id);
}

``

As you can see in the example above I’ve used an AssociativeArray, so I could remove the child with an O(1). There are other places I had to take care of (like KMLDataSource or the updateShow method).

Is there a reason why _children aren’t “AssociativeArray” to begin with?

I could send a PR for this if you think this is a good approach.

Best,

Yonatan

Hi Yonatan!

We’d love to look at a PR if you can cleanly expose this in API! With the Entity API, it just a matter of making sure that all the bookkeeping is organized, and will definitely depend on the approach. Check out the contributor’s guide for how to get started: https://github.com/AnalyticalGraphicsInc/cesium/blob/master/CONTRIBUTING.md

Thanks,

  • Rachel