mapbox / mapbox-maps-ios

Interactive, thoroughly customizable maps for iOS powered by vector tiles and Metal
https://www.mapbox.com/mapbox-mobile-sdk
Other
450 stars 148 forks source link

High Energy Usage #1939

Open OrbitalTech opened 1 year ago

OrbitalTech commented 1 year ago

Environment

Observed behavior and steps to reproduce

Using SwiftUI i am showing a MapBox Map on my main screen, when presented in xcode energy report i have noticed a very high energy usage coming from using to much GPU after hours of debugging i have finally found out that this behavior happens because of mapbox is being re-rendered way too much, i have used the same implementation as their SwiftUI Example, but i am displaying user location on the map and changing the camera when the user moves, additionally i have implemented Apple Maps and Google Maps to see if its General issue with swiftUI or not, and No its specific to MapBox.

So here are some screenshot of whem i am presenting Mapbox and when i remove just the map layer

When i am displaying the map Notice the GPU Usage:

Screenshot 2023-03-25 at 5 06 37 PM

When i remove just the Map Layer Notice how the GPU Usage drops:

Screenshot 2023-03-25 at 5 09 04 PM

Alternatively using Apple Map Or Google Map doesn't use that much GPU.

Expected behavior

Notes / preliminary analysis

So after digging up a little bit more i noticed that with MapBox For some reason calling updateUIView() in the UIViewRepresentable protocol is being called endlessly and very fast which made me think that the GPU usage is because the UI is being redrawn way too much which i am not sure why since with the other map that i experimented with that was not an issue

vladpre92 commented 1 year ago

@OrbitalTech Hi there! One question? Do you have the pulsing animation enabled for the 2D puck? I just noticed that with this animation enabled the CPU is constantly at 40% even with the map idling, which of course affects the energy consumption. Disabling the pulsing animation fixes the high CPU and energy usage.

I see that there is an open ticket on this matter: https://github.com/mapbox/mapbox-maps-ios/issues/1191 but I'm not sure if there is somebody looking at it since it's one year old.

OrbitalTech commented 1 year ago

@vladpre92 Hi i actually had the pulsing animation enabled, and just now i tried to disabled to see if it will make any changes or not, and unfortunately id didn't have an impact, GPU Usage is still high as before.

Screenshot 2023-03-26 at 12 40 24 PM Screenshot 2023-03-26 at 12 41 42 PM
baleboy commented 1 year ago

Thanks for the report. Would you be able to share a small test program that demonstrates the issue? The screenshot is useful but something that can be built in XCode would be better.

goors commented 1 year ago

I did not want to open a new issue. But initial load of the map goes from 35 to 50% of CPU usage. Is that normal?

samskinner32 commented 1 year ago

We are also seeing uncomfortably high CPU usage when we have the user puck enabled.

With this line added to our code: map.location.options.puckType = .puck2D(), we sit at 30-40% CPU, but if I leave that line out I'm sitting at 0-4% CPU.

Even with disabling the pulsing animation, it didn't seem to bring down the usage.

Any way to address this? We're having to disable the puck for now because it's so high

goors commented 1 year ago

I tried many other maps, and it seems to me the only one that have like reasonable cpu 30-40% is this mapbox on load. That other guys Maptiler is at 240% on initial load.

I never use that puck thingy. I am using like simple locationService->getuserlocation->add (or update geojson source for last location) circle layer.

OdNairy commented 1 year ago

Thank you all for providing such detailed reports. We greatly appreciate your efforts in bringing the high CPU usage issue with the Mapbox Maps SDK to our attention. Rest assured, we are fully aware of the problem and have already added it to our backlog for investigation and resolution. However, at this moment, we do not have an estimated time of completion (ETA) for this issue.

In the meantime, we would like to suggest a few known workarounds that you can implement on the application side to mitigate the problem:

  1. Disabling the pulsing animation: The pulsing animation, which adds an infinite animation loop, causes the engine to render a new frame with each VSync call. By disabling this animation, you can reduce the strain on the CPU.
  2. Implementing a custom LocationProvider: Depending on your specific use case, there are several optimizations you can make with the location provider:
    1. Reducing the accuracy of the CLLocationCoordinate2D: While the latitude and longitude values use Double with approximately 15 decimal places, it has been observed that there is no significant difference in GPS data accuracy beyond 6 decimal places. Applying rounding logic to limit the number of unique location points can help alleviate the CPU load.
    2. Filtering duplicated location values: Currently, the Maps SDK passes each location update to the Engine, which triggers frame rendering. By filtering out duplicated location values and passing only unique updates, you can significantly reduce the number of render calls.
    3. Disabling location updates when the location puck is out of the frame: Presently, the Maps SDK sends new location data to the engine regardless of its visibility, leading to unnecessary frame renders. By disabling location updates when the location puck is not in the frame and caching the latest location data to be passed when the camera changes to the user location region, you can optimize CPU usage.
  3. Implementing a custom puck indicator based on UIView: This approach completely removes the workload of the default puck indicator and replaces it with an independent map rendering implementation. Keep in mind that this will impact the interaction of the puck with MapView styles, such as being hidden by extruded building shapes. Additionally, you will need to implement extra logic to handle a pitched state and apply perspective transformations.

We hope these workarounds will provide some relief while we work on a permanent solution for the high CPU usage issue. We truly appreciate your patience and understanding in this matter. Please feel free to reach out to us if you have any further questions or concerns.

darbio commented 1 year ago

@OdNairy Do you have any code examples of how to best implement the above workarounds?

konstantin-tcherkashin commented 10 months ago

@OdNairy It's been 5 months since ticket opening, do you have any estimate now? Is there a release number this fix is scheduled for?

dandyweng commented 9 months ago

@OdNairy Any updates?

teradyl commented 1 month ago

At the very least the puck animation should be disabled by default with clear warnings in the API that this can cause 30+% CPU usage. This was a simple fix to disable the pulsing, but I've been dealing with this for months without realizing the culprit. It's causing lots of CPU usage during debugging and probably worse on people's phones.

Still happening on Mapbox v11.4.0