Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

question: Considerably lower FPS with react-map-gl compared to mapbox-gl #1151

Closed
bkiac opened this issue Jul 13, 2020 · 13 comments
Closed

question: Considerably lower FPS with react-map-gl compared to mapbox-gl #1151

bkiac opened this issue Jul 13, 2020 · 13 comments

Comments

@bkiac
Copy link
Contributor

bkiac commented Jul 13, 2020

I'm having a considerably lower frame rate with react-map-gl components compared to only using mapbox-gl.
In Chrome, sometimes rendering takes twice as much time with react-map-gl. I had better results in Firefox, but it's still slower.
Is this expected or am I missing something obvious about how to handle React re-renders more efficiently?
Maybe #1000 is related to my problem.

I put together an example and uploaded some results of the Chrome profiler.

Thanks for the help!

Tech Version
react-map-gl 5.2.7
Mapbox GL 1.11.1
React 16.12.0
Firefox 78.0.1
Chrome 83.0.4103.116
OS Fedora 32
@bkiac
Copy link
Contributor Author

bkiac commented Jul 14, 2020

I tested it on more environments, and it seems like there is only a substantial difference in Chrome + Linux for some reason.

@nipuna-g
Copy link

I can reproduce this issue with the example attached and on my app.
Using CPU throttling(4x) on Chrome makes the difference even more obvious.

The screen capture below is without throttling.
pan-zoom-issue

Tech Version
Chrome 81.0.4044.138
OS OSX Catalina(10.15.6)

@garretteklof
Copy link

garretteklof commented Aug 19, 2020

I am too having this issue (and as previously referenced similar to #1000). I will also note that I ran into this issue awhile back (several months) but just scrapped it and went with Leaflet because I did not have time to dig and figured that it was my implementation. However, the native MapboxGL seems to improve things quite a bit (some lag but I'm running it full-screen on a 27" 4K monitor with ~50 tabs open).

Right now, I'm just interested in running this for a side project, but do want to begin moving away from Leaflet/VectorGrid on a much bigger endeavor so I'll be monitoring this.

Can someone speak on the main disadvantages with bootstrapping MapboxGL yourself, as opposed to leveraging this library? I'm not at all trying to discount the library just making sure I understand where the discrepancy could be. This library is really 'just' a wrapper on the initialization and provides convenient hooks into the management of viewport state?

edit: I see that there is a whole suite of components so that's obviously a big advantage

@Pessimistress
Copy link
Collaborator

Pessimistress commented Aug 19, 2020

The major difference, and probably where the performance issue originates, is that the camera state of ReactMapGL is managed in React, instead of mapbox-gl. The way mapbox-gl is written is fundamentally incompatible with React, as there are two independent rendering cycles: React's rendering logic, and Mapbox's own animation loop. When you update component props/states, react-map-gl has to synchronize the rendering of React components and the map itself. We have two options:

  • Force map to redraw when React rerenders
  • Block React components from rendering until map renders

We currently use the first approach. This means that redraws happen at React's discretion. React may decide to render more than necessary than Mapbox would on its own, failing to account for how expensive the draw call is.

If you are using mapbox as nothing but a map display, generally speaking you do not need this library. If you are trying to match the map with any other React component, you will eventually run into the same issue.

@dyakovlev
Copy link

dyakovlev commented Apr 21, 2021

We're running into this issue as well, using Mapbox GL and ReactMapGL in an interactive application. It seems to have gotten worse in the last few months.

I had some success in throttling viewport updates, as it seemed that the sheer quantity emitted when panning a map was flooding the InteractiveMap component to the point of it no longer rendering at all.

Some basic profiling points to a lot more of setState in InteractiveMap than anything else, but I haven't absorbed it in depth.

Would it be viable to emit viewport state updates in reaction to motion, but to allow the GL instance to pan itself instead of being controlled by props?

@Pessimistress
Copy link
Collaborator

You can set asyncRender={true} on the map component. This will cause the React Markers & Popups to go out of sync during viewport updates, but have been reported to improve the render performance.

@spiffistan
Copy link

Running into this issue as well. Zooming and panning is super slow, especially with trackpads, and transitionDuration does nothing to ameliorate the problem. It seems to be the setState for viewport updates causing the problem.

@dyakovlev
Copy link

^^ yes, we've had to throttle viewport updates for scrolling and panning events to once per 30ms, as unfortunately we have on-screen elements that go out of sync with asyncRender. (performance did get a lot better, but the state tearing was visually unacceptable)

It's consistently choppy, but feels better than being inconsistently choppy.

@justindchan
Copy link

IF one uses the original mapbox api and not the react library is this problem alleviated?

@Pessimistress
Copy link
Collaborator

This is being addressed in v7.0. Please follow #1646

@JessicaBunyan
Copy link

JessicaBunyan commented Jun 30, 2022

Just as info for any future searchers, we switched to mapbox v7 and used the uncontrolled map component, as well as using geoJSON to show markers with a datalayer (with step expressions to show different markers if needed)

With these changes we went from struggling at 200 markers (unusable at 300) to showing 1400 and is smoother than ever

Our challenges with this were:

  1. Accessibility / tab navigation - this is lost when using geojson rather than react elements
  2. Programmatic pan/zoom - This is lost when using uncontrolled map component. We circumvented this by unloading/reloading the map when we need to do this, by re-setting its key prop. Its not ideal but it does the job after a fashion This can be handled with a ref on the map and map.easeTo or map.jumpTo

@Pessimistress
Copy link
Collaborator

Programmatic pan/zoom

You can call map.easeTo and map.jumpTo using a ref.

@JessicaBunyan
Copy link

That's great, thanks for the info @Pessimistress !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants