Avoid map repaint when setting same parameter value that is already being used#97
Conversation
| } | ||
| if (target.id === undefined) { | ||
| this.fire(new ErrorEvent(new Error(`The feature id parameter must be provided.`))); | ||
| return false; |
There was a problem hiding this comment.
There wasn't any return here originally. This might have API impact if there's a feature with id undefined?
(During development I also came across other spots which used throw instead of this.fire; however, I assume that firing events is usually better)
|
Bundle size report: Size Change: +165 B
ℹ️ View Details
|
|
This probably needs some additional documentation (whenever we have maplibre docs.. #19). We now ran into a similar issue for #106 where we occasionally reupload the same ~20MiB GeoJSON. A I'll create an issue about this after merge, so we can document it in the future. |
|
Hi @JannikGM. This looks good to me, but I don't consider myself qualified enough in the codebase to be the only reviewer given the number of changes. |
| if (before && newIndex === -1) { | ||
| this.fire(new ErrorEvent(new Error(`Layer with id "${before}" does not exist on this map.`))); | ||
| return; | ||
| return false; |
There was a problem hiding this comment.
We already did this._order.splice(index, 1); so this should probably return true.
Otherwise, if we move a layer with a bad target it will be removed from the model but the map won't update correctly.
|
Hi Jannik. The CI should work now. Can you fetch upstream and merge into your branch? Thanks. |
HarelM
left a comment
There was a problem hiding this comment.
Looks good to me. If we find other API calls that needs checking we can always add them in the future.
|
@JannikGM can you merge from main and fix the lint warnings about the jsDocs? |
|
@JannikGM can you redo these changes on top of main so I can merge this? |
|
This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days. |
|
This PR was closed because it has been stalled for 30 days with no activity. |
Our map has performance issues due to paint-, layout-properties or filters being touched within a "mousemove"- or
requestAnimationFramehandler. Even though we set the same value every time, mapbox will still decide to repaint.We have many sources and layers, so repainting is slow (see #96) and should be avoided if possible.
While we will likely fix this in our own app by how we use the API, I feel this should also be guarded against by the API itself.
Even mapbox samples themselves do redundant changes in "mousemove" handlers, so I believe that many users will be affected by this.
Internally, mapbox also guards against this (which prevents some computations, but still triggers a repaint).
Mapbox also already guards against redundant changes for setters in the API.
This PR extends the internal checks (more of them) and returns a boolean whether an early-out was taken.
This information is then used to skip
map._updatewhich will then avoid an expensivemap.triggerRepaint.I tried to fix as many affected functions that I'm aware of, but I might not have guarded everything. There are also plenty of situations where these guards will fail.
I'm aware of the following shortcomings and potential issues:
setFeatureStatewill report slightly better errors for unknown keys, because error-checking might already occur ingetFeatureState.removeFeatureStateis very incomplete. Removing a missing-key will trigger repaints anyway. Some code is already present, I just didn't deep dive into the feature-state deletion logic.jumpToare handled, buteaseToisn't.setFeatureStatemight be considerably slower / unusable if large objects are passed into it. We basically trust that people don't throwwindowor similar into a feature-state (which would potentially take a long time to compare).returnthat might affect behaviour for a niche case; I'll leave a review comment to point it out.Following is code I've been using for testing this feature. I don't check all features though, so there might be bugs left.
Note that master will repeatedly draw with the following code, thereby causing high CPU and GPU usage.
With my proposed change, maplibbre will not draw because changes are redundant.
I have not used this code in production yet, so this has gotten very little testing.
The automated tests in mapbox aren't designed to test for this either (I don't think adding a test for this is necessary though).