Bug: _clearIIf in init.js has O(n^2) performance(JavaScript API)

250
0
12-02-2016 11:22 AM
Status: Open
TravisWatkins1
New Contributor II

I have included the functions from the arcgis_js_v318_api.zip download below. (this functionality is mostly unchanged from 3.13, with only the 'if(b)' bypass being added in 3.18)

As you can see, the _clearIIf function loops over the elements from the last graphic to the first, then the remove function loops over the graphics elements from the first to the last to find it, always looking at every single graphic element before finding the one to remove.  (_removeFeatureIIf is included as it links the two other functions)

If 80,000 graphics items are present, then the browser will pause for ~4 minutes, but at 10,000 graphic items, it only takes about 4.5 seconds on the same machine.  And as this all takes place before any server calls, it can not be a networking issue.

In testing, reversing the loop in the remove function improved performance by a factor of 3, but it was still O(n^2) to clear the map. (it looks like the delete function may also have a forward loop)

In 3.18 it looks like a by-pass may have been added for cases where no elements are selected on the map, 

From \arcgis_js_v318_api\arcgis_js_api\library\3.18\3.18\init.js:
_clearIIf:function(){
    var a;
    a=this.featureLayer;
    var e=a.graphics,c=a._selectedFeatures,b=a.getSelectedFeatures().length,d=a.objectIdField;
    if(b)
        for(a=e.length-1;0<=a;a--){
        var b=e,g=b.attributes;
        g in c?b._count=1:(b._count=0,this._removeFeatureIIf(g))
    }
    else a.cle...

}

_removeFeatureIIf:function(a){

    var e=this._featureMap,c=this.featureLayer;

    if(e){

        if(e._count)return;

        delete this._featureMap;

        c._remove(e)

    }

    return e

}

From: \arcgis_js_v318_api\arcgis_js_api\library\3.18\3.18\dojox\gfx\svg.js
remove:function(a,c){
    for(var b=0;b<this.children.length;++b)
        if(this.children==a){
            c||(a.parent=null,a.parentMatrix=null);
            this.children.splice(b,1);
            break
        }
        return this
}