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

Coalesce high-frequency 'setData' calls #5902

Merged
merged 1 commit into from
Jan 3, 2018
Merged

Conversation

ChrisLoer
Copy link
Contributor

This is an exploratory PR motivated by various example animations provided in #5716. The common theme was using high-frequency setData calls to animate items in a GeoJSON source.

When you send setData calls to the source faster than they can be processed, you end up with an unbounded backlog of requests on the GeoJSON worker, and every request gets processed in order (also several reloadTile requests get added to the backlog for every setData) no matter how far behind you are. Non-GeoJSON requests to the same worker may also starve.

This PR introduces a coalescing mechanism on setData so that the worker will always finish any loadData call it starts, and it will always process the last loadData it receives, but it is allowed to discard calls that arrive while it is already in the middle of processing an earlier request.

I couldn't figure out a good way to self-send a "coalesced" message so I ended up round-tripping a "coalesce" message back to the parent, which adds a little latency but I think should still be correct.

The set_data.html debug page contains a relatively slow setData animation that exercises this functionality, and there are currently log statements that record how many calls are getting coalesced.

On my machine, this demo page works ok without the coalescing, and coalescing only seems to skip roughly half of the setData calls, so maybe this isn't that important an optimization. But just upping the size of the GeoJSON feature set is enough to make the animation start developing a large backlog if it doesn't have coalescing enabled.

/cc @ansis @jfirebaugh @andrewharvey

@ChrisLoer ChrisLoer added performance ⚡ Speed, stability, CPU usage, memory usage, or power usage under development labels Dec 20, 2017
@andrewharvey
Copy link
Collaborator

@ChrisLoer This is great! Although I don't notice much improvement in terms of the draggable symbol being 100% in sync/as fast as the cursor, I do notice it's no longer playing catchup with the cursor and instead closer to where it should be.

Sounds related to #4271 and #3692 ?

@ChrisLoer
Copy link
Contributor Author

Sounds related to #4271 and #3692?

Yup. I didn't know about #3692, but it sounds like I've implemented something similar to #3692 (comment). Maybe this is enough to solve all of that problem?

@ChrisLoer
Copy link
Contributor Author

I don't notice much improvement in terms of the draggable symbol being 100% in sync/as fast as the cursor

Yeah, fundamentally using GeoJSON for this kind of animation can be problematic (re-uploading/re-parsing the entire GeoJSON data set for every motion). Longer term we're interested in adding some sort of interface that would be more efficient for this type of animation.

@ryanbaumann
Copy link
Contributor

Nice @ChrisLoer. Going to test this branch for common animation use cases cc @cmtoomey

@ChrisLoer
Copy link
Contributor Author

I added some comments and shortened the "coalesce" callback slightly by sending the "coalesce" message directly from the loadData callback, instead of sending a separate "coalesce" message to the foreground and waiting for it to get echoed back.

Playing around with different sizes of data set gave me an appreciation for why we might want to build in (separate?) time-based throttling. Although the current changes prevent the worker from building up an arbitrarily long queue, it's still easy to peg the map with enough requests to make everything feel pretty sluggish. It's easy to extend the coalescing behavior to include a maximum frequency (say, once every 100ms) that prevents pegging to 100% CPU usage for what should be relatively cheap. But it's a trade-off: some animations will look smoother running as fast as they can...

@ChrisLoer ChrisLoer changed the title POC: coalesce high-frequency 'setData' calls Coalesce high-frequency 'setData' calls Jan 2, 2018
This prevents high-frequency calls to setData from building up a backlog.
@anandthakker
Copy link
Contributor

👏

ChrisLoer added a commit that referenced this pull request Jan 19, 2018
Re-implement PR #5902 including fix for issue #5970.
@mb12
Copy link

mb12 commented Jan 22, 2018

@ChrisLoer and @anandthakker Would throttling of setdata calls be added to native as well?

@ChrisLoer ChrisLoer deleted the coalesce-set-data branch January 22, 2018 21:11
@ChrisLoer
Copy link
Contributor Author

@mb12 I haven't looked at it closely, but I think the architecture on native is fairly different (I think the equivalent GeoJSONSource::setGeoJSON actually runs synchronously?). So I don't think we'd do a direct port of this change -- although there are probably analogous situations where frequent calls to something like (on iOS) MGLShapeSource::setShape could build up a backlog of requests.

@ChrisLoer ChrisLoer mentioned this pull request Jan 25, 2018
ChrisLoer added a commit that referenced this pull request Jan 25, 2018
Re-implement PR #5902 including fix for issue #5970.
ChrisLoer added a commit that referenced this pull request Jan 25, 2018
Re-implement PR #5902 including fix for issue #5970.
ChrisLoer added a commit that referenced this pull request Jan 29, 2018
Re-implement PR #5902 including fix for issue #5970.
kturney added a commit to kturney/ember-mapbox-gl that referenced this pull request Feb 1, 2018
mapbox-gl-js handles it itself since mapbox/mapbox-gl-js#5902
kturney added a commit to kturney/ember-mapbox-gl that referenced this pull request Feb 1, 2018
mapbox-gl-js handles it itself since mapbox/mapbox-gl-js#5902
kturney added a commit to kturney/ember-mapbox-gl that referenced this pull request Feb 2, 2018
mapbox-gl-js handles it itself since mapbox/mapbox-gl-js#5902
kturney added a commit to kturney/ember-mapbox-gl that referenced this pull request Feb 2, 2018
mapbox-gl-js handles it itself since mapbox/mapbox-gl-js#5902
pathmapper pushed a commit to pathmapper/mapbox-gl-js that referenced this pull request Feb 13, 2018
Re-implement PR mapbox#5902 including fix for issue mapbox#5970.
pathmapper pushed a commit to pathmapper/mapbox-gl-js that referenced this pull request Feb 13, 2018
Re-implement PR mapbox#5902 including fix for issue mapbox#5970.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance ⚡ Speed, stability, CPU usage, memory usage, or power usage
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants