Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cause of MapBox GL JS Performance Difference

This question is for someone who understands the internals of MapBox GL JS.

I'm using MapBox GL JS to render a geographic map of up to 40,000 polygons, each of which is colored based on the "owner" of that polygon. There are typically many polygons per owner and the "owner" of each polygon may change over time. The number of owners can vary from one to around 1,000. I'm having performance problems (which vary depending on how I approach it), so I've tried a few different strategies.

  1. Using data-driven styling for "fill-color", where I have a single source and a single layer. I've tried both the polygon id and the "owner" id as the category for the data-driven styling.
  2. Using filtered layers, where I have a single source and a separate layer for each "owner". Again, I've tried both the polygon id and the "owner" id as the criteria for filtering.
  3. Using a separate source and layer for each "owner".

Option three has the best drawing speed. The layers are rendered very fast as I zoom and pan. But I have to call setData whenever I change the owner of a layer and setData leaks memory so I eventually end up with the page crashing. This issue, 2607, was closed as not actionable, so I don't expect a resolution to this.

Options one and two draw okay with the initial zoom, but when I zoom in they are very slow to re-draw the tiles. I am stuck looking at the jagged, low detail tiles until the rendering catches up after 20-30 seconds. Note that if I use the "owner" id instead of the "polygon" id, I still need to call setData when an "owner" changes which will lead to the memory leak. If I use polygon id, I just need to update the layer filters or fill-color categories when the "owner" changes. However, I don't get a noticeable performance difference if I use "polygon" id so I think that's okay.

So my question is why is option three so much faster to render when I zoom in? Does it have to do with the number of workers assigned to drawing? In options one and two, there is a single source so does that mean the drawing is only using a single worker? Whereas in option three, there is a separate source for each "owner" so I have multiple workers doing the drawing?

like image 691
jasonpepper Avatar asked Nov 03 '16 15:11

jasonpepper


People also ask

Does Mapbox use JavaScript?

Mapbox GL JS is a JavaScript library for vector maps on the Web. Its performance, real-time styling, and interactivity features set the bar for anyone building fast, immersive maps on the web.

Is Mapbox better than Google Maps?

Both Google Maps and Mapbox support the idea of customization, but customization is the main strength of Mapbox. Google map is a bit strict or we can say less flexible when it comes to customization. Google Maps enforce you to use its default base layer, on the other hand, there is no such restriction on Mapbox.

How does Mapbox GL work?

Mapbox GL fetches geospatial data from vector tiles and style instructions from a style document and helps the client draw 2D and 3D Mapbox maps as dynamic visual graphics with OpenGL.


2 Answers

I recommend performing a data-join using categorical data-driven styles. This allows you to decouple your data property updates from your geometry.

Check out https://www.mapbox.com/mapbox-gl-js/example/data-join/ for an example of how to join JSON data in the browser to vector tile geometry. This should scale well up to 100+ thousand features.

like image 65
Ryan Baumann Avatar answered Oct 12 '22 13:10

Ryan Baumann


I think you will require a variety of techniques to solve what is essentially a level of detail (LOD) problem. I've done similar work involving drawing poly regions of a country to indicate various Districts within a State and you have to scale data to suit the view.

The first thing I would recommend is creating various levels of detail for your Regions. A first-sweep can be done automatically by removing Region vertices that are aligned (geographically speaking) within a few degrees of a straight line with their neighboring points. Think of this as removing the many small points that don't add detail to a Region boundary as they are on a straight line. As this can be an automated (and even pre-stored) step you can create different levels of detail based on zoom-level.

The second recommendation is view-space culling. That is, if a region is not within the view port, don't render it! If you attempt to do this vertex-perfect you'll end up with the same CPU problems as before so I'd recommend creating a Region bounding-box (if you are using axis-aligned viewing only, a suggestion proposed as it's the easiest solution).

If you need non axis-aligned regions, simply create a bounding circle (with a radius based on the boundary vertex at the greatest distance from the geocentre of the region).

I would suggest that your various difficulties are a derivative of the scene complexity problem. Solve that and you will have a much more efficient system to work with.

Good luck!

like image 38
Monza Avatar answered Oct 12 '22 14:10

Monza