nebula.gl
nebula.gl copied to clipboard
Poor panning-by-dragging performance with multiple layers
Describe the bug
When working with large data sets (10,000s of features across multiple EditableGeoJson layers), panning [edit: by dragging] slows to a crawl, because each layer calls this.getPicks(...) whether its mode needs picking data or not. Worse, it's called both in _onpointermove and _onpanmove which both fire.
I suspect the picks object passed to all should be replaced with a lazy object / callable function, so it can be invoked only when needed.
Actual Result
Panning can slow down to a few FPS
Expected Result
Panning FPS is unaffected by large datasets
Some notes that might help your investigations:
In deck.gl, layers have a pickable property that can be set to false to exclude them from the picking process. Then you can call the various deck.pick... functions yourself when you do what to pick.
Another thought is that the auto highlighting feature does require picking on mouse move, you can also turn that off via the autoHighlight layer prop.
Thanks @ibgreen.
The issue I have is that I do want all of my EditableGeoJsonLayers to be pickable, for using getTooltip, selecting features on click, etc. If I convert the layers to vanilla GeoJsonLayers, or disable _onpointermove and _onpanmove by monkey-patching, the drag-to-pan and deck.gl picking performance is fantastic, even with >100k features on >40 layers.
When dragging with multiple large EditableGeoJsonLayers, all the processing time is spent in per-layer calls of pickMultipleObjects:

I've yet to find an approach that allows me to avoid those unnecessary computationally-expensive hooks, while preserving standard EditableGeoJsonLayer picking functionality.
Had a brainwave re. a workaround right after posting: a layer subclass which disables the offending hooks, swapped in when they're unneeded (e.g. when the mode is ViewMode:
class ViewOnlyEditableGeoJsonLayer extends EditableGeoJsonLayer {
_onpointermove() { }
_onpanmove() { }
}
// in my deck-updating logic:
const layerClass = mode == ViewMode ? ViewOnlyEditableGeoJsonLayer : EditableGeoJsonLayer;
layers.push(new layerClass(layerProps));
deckInstance.setProps({ 'layers': layers });
This seems to fix performance while preserving layer state, but is limited to my use case, so I'm inclined to leave the issue open, as I think this affects the library's ability to scale.
pickMultipleObjects is very expensive as it requires multiple GPU readouts. It should not be called on pans, just on clicks. If I was looking at making changes to the code that would be my starting point.