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

Cache style layers and sources #364

Closed
LukasPaczos opened this issue May 24, 2021 · 16 comments
Closed

Cache style layers and sources #364

LukasPaczos opened this issue May 24, 2021 · 16 comments

Comments

@LukasPaczos
Copy link

The pre-v10 Style object cached layers and sources on the platform side to avoid having to fetch them from native whenever getter methods were called (refs mapbox/mapbox-gl-native#13484).

In v10, this is not available anymore and as mapbox/mapbox-navigation-android#4425 (comment) shows, the constant recreation of style objects (getStyleLayerProperties in this case) causes a considerable performance penalty when called frequently (on each animation frame in this case).

It'd be great if we can reintroduce some sort of platform caching or measure the performance of the native getStyleLayerProperties to see whether just crossing the JNI boundary and marshaling is the bottleneck or whether the native method itself could be optimized.

cc @mapbox/maps-android @cafesilencio

@LukasPaczos
Copy link
Author

Adding a more detailed profile screenshot:
Screenshot from 2021-05-24 13-15-47

@pengdev
Copy link
Member

pengdev commented May 26, 2021

We have these values cached in the style layer and source classes already, just for consistency we decided to go through the gl-native to get the latest property values, since they could be modified in other places. Do you think we should always return the cached values? Or shall we introduce some flags to toggle the cache/without cache getters?

Optionally, I think we could also expose the entire cached Property HashMap if that's helpful.

@LukasPaczos
Copy link
Author

Property values are one thing (that I didn't measure) and it does make sense to always ask GL-Native for that since it's the source of truth. The concern here is about obtaining the layer/source reference itself (StyleManagerInterface#getStyleLayerProperties). Whenever a layer reference is first obtained from native, we could cache it in a map on the platform side so that all subsequent calls return a cached value instead of asking GL-Native again. We'd have to only drop that cached reference when removeLayer/Source is called or the style is reloaded.

@LukasPaczos
Copy link
Author

We could also use styleLayerExists/styleSourceExists before returning the cached reference since those methods seem to be much faster.

@pengdev pengdev self-assigned this Jun 23, 2021
@pengdev
Copy link
Member

pengdev commented Jun 23, 2021

Hi @LukasPaczos I tried to read through the ticket again, I think the bottleneck is the call of getStyleLayerProperties when you are using style.getLayer(layerId) API. The getStyleLayerProperties is pretty heavy since it tries to retrieve all the layer properties. I think we can optimise it to use two simple and lighter getStyleLayerProperty APIs, since we just need the layer type and source to construct the Layer.

I'm working on a PR to optimise it at #449 , do you want to do some benchmarks using a snapshot build?

@LukasPaczos
Copy link
Author

@pengdev happy to take it for a spin whenever you think it's ready 👍

@pengdev
Copy link
Member

pengdev commented Jun 23, 2021

@LukasPaczos thanks! I have triggered a snapshot, you can try 10.0.0-rc.1-peng-improve-getLayer-api-SNAPSHOT when you have time.

@pengdev
Copy link
Member

pengdev commented Jun 24, 2021

@LukasPaczos I did some profiling on this change, in the same benchmark, the CPU utilisation seems to be improved

Before(getLayer takes 12.1% CPU time, getStyleLayerProperties takes 8.7% CPU time):
Screenshot 2021-06-24 at 19 10 25

After(getLayer takes 5.47% cpu time, getStyleLayerProperty takes 2.14% CPU time):
Screenshot 2021-06-24 at 18 55 52

@LukasPaczos
Copy link
Author

My benchmarks integrating the snapshot into the Nav SDK are even more promising given the frequency with which we call all the methods.

Before
Screenshot from 2021-06-25 12-33-49
Screenshot from 2021-06-25 12-34-48

After
Screenshot from 2021-06-25 12-35-18
Screenshot from 2021-06-25 12-35-36

A decrease of ~42 percentage points of time spent in the getStyleLayerProperties!

It still is not negligible, and now the bottleneck becomes the setStyleLayerProperties, but definitely the right direction.

@pengdev
Copy link
Member

pengdev commented Jun 28, 2021

@LukasPaczos What's the code path to the setStyleLayerProperties call? I can try to look where we can optimise.

@pengdev
Copy link
Member

pengdev commented Jun 29, 2021

Setting the lineGradient and the under hood setStyleLayerProperty seems not avoidable on the platform side. @LukasPaczos could you suggest how I could simulate the navigation session with the gradient line in use? I will try to run the exact the same code and do more benchmarking.

@LukasPaczos
Copy link
Author

@pengdev you can try updating the gradient every time the OnIndicatorPositionChangedListener fires. We do that for 3 line layers in the Nav SDK.

@pengdev
Copy link
Member

pengdev commented Jul 21, 2021

The performance of setStyleLayerProperty with complex expressions seems to be the main bottle neck currently, we need to solve it by optimising the Value marshalling.

@stale stale bot added the archived label Apr 18, 2022
@kiryldz
Copy link
Contributor

kiryldz commented Oct 25, 2024

Stale, outdated.

@kiryldz kiryldz closed this as completed Oct 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants