maplibre / maplibre-gl-directions

A plugin to show routing directions on a MapLibre GL JS map
https://maplibre.org/maplibre-gl-directions/
MIT License
72 stars 16 forks source link

Performance for large routes #229

Closed allencoded closed 2 months ago

allencoded commented 3 months ago

I have implemented the maplibre directions into my project, but I noticed it has very wild performance spikes. If you add multiple waypoints and start moving the waypoints around you get massive spikes in CPU usage and things slow down to a crawl. I am looking for help with improving the performance.

I am using Mapbox as my routing provider with the routing option set to full. This is required due my users desires on having the lines match the roads. We use NextJS so react code. Here is my code to reproduce:

export function Map() {
  const mapRef = useRef<HTMLDivElement>(null);
  const [directions, setDirections] = useState<MapLibreGlDirections | null>(
    null,
  );
  const { setMap } = useMapStore();
  useEffect(() => {
    const initializeMap = () => {
      if (!mapRef.current) {
        throw new Error('Map container is not initialized');
      }

      return new maplibregl.Map({
        container: mapRef.current,
        style:
          'https://api.maptiler.com/maps/streets-v2/style.json?key=[MYKEY]',
        center: [0, 0],
        zoom: 2,
      });
    };

    const mapLibreMap = initializeMap();
    mapLibreMap.on('load', () => {
      const directionsInstance = new MapLibreGlDirections(mapLibreMap, {
        api: 'https://api.mapbox.com/directions/v5/mapbox',
        requestOptions: {
          access_token:
            '[MY_ACCESS_TOKEN],
          overview: 'full',
        },
      });
      setMap(mapLibreMap);
      setDirections(directionsInstance);
    });
  }, [setMap]);

  useEffect(() => {
    if (directions) {
      directions.hoverable = true;
      directions.interactive = true;

      directions.on('fetchroutesend', (e) => {
        if (e.data && e.data.code !== 'Ok') {
          console.error(e);
        }
      });
    }
  }, [directions]);

  return (
    <div id="map" ref={mapRef} style={{ width: '100vw', height: '100vh' }} />
  );
}
smellyshovel commented 3 months ago

Hello,

If you add multiple waypoints

which numbers are we talking exactly?

massive spikes in CPU usage and things slow down to a crawl

Could you please be more specific? Maybe sharing a minimal reproduction? Performance profiler's output? Or at least a screen recording?


In general, I wouldn't say I'm too surprised about it. I remember having similar issues back in the time of development of the first version of the plugin. However, I realized back then that (at least for my exact case) the mere fact of measuring the performance made things worse. Moreover, only having the devtools open reduced the performance by a visible amount.

On the other hand, the issues may be (and most probably are) real, given that the more features you've got drawn on your map (including the basemap, custom layers and the Directions Plugin's features - all together), the harder will be the performance drop. On each idling (in between of each redrawing, in other words), when having the interactivity enabled, the plugin needs to query all the currently rendered features, then get the cursor position, then loop through all the rendered features and check whether the cursor collides any of the drawn features. Then, if it does, it checks which layers the features belongs to and so on and so forth. So, you can see the direct correllation between the amount of features not only plugin-related, but the total amount of features drawn on the map, and the time it requires for the interactivity to properly work.

Do you experience performance-related issues when having the directions plugin completely disabled?

smellyshovel commented 3 months ago

Some algorithms of the plugin can definitely be improved, I'm pretty much sure about it (though I wouldn't say that this is a top priority for me now - however, PRs are welcome). On the other hand, I believe that in your particular case the issue is brought into scope by those algorithms which we don't have direct access to. In other words, I really doubt we can do anything here. But first we need to see the Profiler's reports to understand what are we dealing with.

Anyway, thanks for bringing this one in. I always felt like there may be such issues, but almost never really noticed anything of the sort. So, let's try to figure ouy what's going on.

smellyshovel commented 2 months ago

Closing for no response for now. If there's any new info, feel free to reopen.