Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

iOS user tracking mode = follow leads to excessive CPU usage #7236

Open
danpat opened this issue Nov 30, 2016 · 28 comments
Open

iOS user tracking mode = follow leads to excessive CPU usage #7236

danpat opened this issue Nov 30, 2016 · 28 comments
Assignees
Labels
Core The cross-platform C++ core, aka mbgl iOS Mapbox Maps SDK for iOS navigation For the Mapbox Navigation SDK for Android or iOS or navigation use cases in general performance Speed, stability, CPU usage, memory usage, or power usage
Milestone

Comments

@danpat
Copy link

danpat commented Nov 30, 2016

Platform: iOS
Mapbox SDK version: 3.4.0-beta.4

Steps to trigger behavior

  1. Create a map
  2. Call mapView.setUserTrackingMode(.follow, animated: true)
  3. If simulating, feed in a GPX trace. If outside, walk around.
  4. Watch 1 thread use 100% CPU
  5. Swipe the map to cancel user tracking
  6. Watch the CPU usage return to baseline

The value of animated: does not seem to have an effect on CPU usage. true/false both lead to one pegged core.

screen shot 2016-11-29 at 23 54 03

Small video showing the CPU changes with tracking mode changes with the iOS simulator:

https://www.youtube.com/watch?v=_71Hoz_7neA&feature=youtu.be

Expected behavior

Animating the map to follow the user marker shouldn't consume an entire core.

Actual behavior

My phone gets really hot and the battery drains quickly. My wife gets angry that she can't call me because my phone is dead. I get lost in the wilderness because I no longer have maps.

@1ec5 1ec5 added Core The cross-platform C++ core, aka mbgl iOS Mapbox Maps SDK for iOS performance Speed, stability, CPU usage, memory usage, or power usage navigation For the Mapbox Navigation SDK for Android or iOS or navigation use cases in general labels Nov 30, 2016
@1ec5
Copy link
Contributor

1ec5 commented Nov 30, 2016

Note that #6060 and #7125 do not address this issue because the camera changes significantly on each location update.

/cc @incanus @bsudekum @willwhite

@1ec5
Copy link
Contributor

1ec5 commented Jan 24, 2017

I’m moving this issue to v3.5.0, because a complete fix will require beta testing and possibly changes to mbgl. However, note that #7125 remains on the milestone, and #7724 has landed.

@1ec5 1ec5 modified the milestones: ios-v3.5.0, ios-v3.4.1 Jan 24, 2017
@1ec5 1ec5 modified the milestones: ios-v3.5.0, ios-v3.6.0 Mar 9, 2017
@boundsj boundsj modified the milestones: ios-future, ios-v3.6.0 Apr 5, 2017
@stale stale bot added the archived Archived because of inactivity label Nov 10, 2018
@stale
Copy link

stale bot commented Nov 27, 2018

This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions.

@stale stale bot closed this as completed Nov 27, 2018
@chloekraw chloekraw reopened this Mar 31, 2019
@stale stale bot removed the archived Archived because of inactivity label Mar 31, 2019
@pappalar
Copy link

Hello, do you plan to include a fix for this issue in one of the next releases?
Following user location with the SDK causes this CPU spikes also in 4.9

@pappalar
Copy link

I'd like to point out that the same issue in the Android SDK is caused by the heavy usage of the compass component.

this Might be related?

@fabian-guerra fabian-guerra self-assigned this Apr 22, 2019
@fabian-guerra
Copy link
Contributor

I'm testing version 4.10.0 on an iPhone X iOS 12.2, seems that we have spikes but profiling with instruments some are related to the core libraries but goes down immediately. The larger spikes in this chart are me playing with zooming in/out.

cpuusage

@racer1988 could you please post a screenshot of what you are seeing.

@pappalar
Copy link

pappalar commented Apr 24, 2019

@fabian-guerra This is my graph when changing the map TrackingMode

Screenshot 2019-04-24 at 10 15 05

the issue seems to be identical to the one that the reported initially raised.

Unfortunately I can't profile on the device and go around to reproduce the same.
If you know how to run a GPX simulation while profiling, I'd be happy to try that.

Just by profiling and tracking user location I can see the map spiking to 50% and most of the usage is due to MapBox rendering:

I guess following user location is triggering re-rendering on the map somehow in a heavy way.

The usage of the total CPU cores in Xcode is around 50%, where Thread 1 is stuck at 100%.
Memory consumption goes to very high.

Doing the same exact test with Mapkit sets the thread around 7/8 %

Screenshot 2019-04-24 at 11 13 04

@fabian-guerra
Copy link
Contributor

@racer1988 which map's SDK version are you testing? What's the device?

@pappalar
Copy link

Tested with both 4.9 and 4.10
This graph comes from a iPhone X

the same is visible on the simulators if using a GPX track to reproduce the location

@fabian-guerra
Copy link
Contributor

Using 4.9.0

Again the spikes are me zooming in/out panning
cpu2

@racer1988 do you have a test app we could use to track down the issue?

@pappalar
Copy link

I currently don’t have access to my laptop. I don’t have a existing app,
I would need to create a new one to share.
I could check next week.

If it can help, I am hosting the map in a child view controller that is then included in the main one. Not sure how this is relevant, but might have different layout passes than a direct use of the map

@pappalar
Copy link

@julianrex @fabian-guerra I stripped down my production code to a basic map and I am able to reproduce in 100% of the cases.

You can find the code and reproduce yourself from here: https://github.com/racer1988/mapboxIssue

Important Notes:

  • I did not put a token, so the map is not rendered. Even with that, the issue still occurs!
  • The spike also happens while zooming in the first time by starting to track the user location. (the spike then goes down when the camera goes idle)

How to reproduce:

  • Use CocoaPod to install MapBox (and PureLayout)
  • Run the app on a random simulator
  • Simulate the location in Xcode with a random GPX: I provided 2014-04-09_2527084_test-iphone-5s_export_xcode.gpx so you can use that one directly.
  • Click on the blue button on the map to cycle between: ModeFollow -> ModeFollowWithHeading -> ModeNone

you can see the same behaviour reported by me and @danpat :

Screenshot 2019-04-29 at 14 38 37

The TrackingMode button is the following one:

Screenshot 2019-04-29 at 14 30 01

@pappalar
Copy link

pappalar commented Apr 29, 2019

This is what I can see when clicking tracking for the first time and the zooming kicks in:

Screenshot 2019-04-29 at 14 49 47

EDIT:

You can reproduce while profiling using the Simulator debug location (eg: Freeway ride)

Screenshot 2019-04-29 at 14 54 00

@julianrex
Copy link
Contributor

@racer1988 thanks so much for providing a test case!

@fabian-guerra
Copy link
Contributor

fabian-guerra commented Apr 29, 2019

Hi, @racer1988. Thank you for the test app.

It seems that this is related to the gpx file update frequency. I looked into our logs (you also can, take a look at this config), and realized there were 4~5 updates per second. Playing with the file to update every second I got the following chart:

onesecond

You can modify the file changing the time as it's suggested here: https://stackoverflow.com/a/36416589/1919929

In case you need, we have an API that will let you simulate location updates: https://docs.mapbox.com/ios/api/maps/4.10.0/Location%20Updates.html and an example on how to implement it is in: https://github.com/mapbox/mapbox-gl-native/blob/master/platform/ios/app/MBXCustomLocationViewController.m

@danpat
Copy link
Author

danpat commented Apr 29, 2019

@fabian-guerra Even at 4-5hz, if there's no map being rendered, what on earth is eating up all the CPU time? Why are location updates so CPU intensive if there's nothing to render?

@fabian-guerra
Copy link
Contributor

fabian-guerra commented Apr 29, 2019

@danpat I'm still researching this issue. Location management technology is cpu intensive. That being said don't know if Apple has some sort of optimizations for gpx files in MapKit. This chart is from our API that simulates a location manager with a route in SF, and userTrackingMode set to follow.

mapboxlm

@pappalar
Copy link

@fabian-guerra the same behaviour in spike of CPU happens even with a fixed location when the tracking is set to follow and the map is slowly zoomed from level 1 to the max zoom level.

There the issue looks the same, however the cause can't be the location updates, as there are none.
To me it looks like something else is eating CPU time

@fabian-guerra
Copy link
Contributor

@racer1988 a fixed location in a gpx file?

@friedbunny
Copy link
Contributor

Without having any knowledge of this specific issue, one optimization that @LukasPaczos implemented on Android seems worth investigating on iOS — #13678 — the idea being that we attempt to update the user location too frequently and for no real/visible benefit.

@pappalar
Copy link

pappalar commented Apr 29, 2019

@fabian-guerra 2 more points here for your investigation:

  1. No, no need for a GPX.

You can simulate the issue two ways:

  • On a simulator, launch the app, go to the location picker and choose a fixed one provided by apple. then switch to TrackingFollow (from None)
  • On a Device: launch the app and switch tracking mode to zoom to your location.

Even with this simple case, the CPU spike is the same (eats 100% Thread), the inspector shows the same issue (see image at the bottom)

This is a simple case of a user wanting to zoom to his location.
Even in this case, the camera updates are eating the full Thread, without anything really rendered

  1. The CPU is not going to 100% if the Location is updated without modifying the viewport even with the fast GPX file.

To simulate, start the GPX file, start following the user, then slighly pan away, to fallback to tracking None.

When the location annotation is in the viewPort, but the tracking is set to NONE, the CPU is at 0%
and only didUpdateUserLocation is printed. (same if location is outside the viewport)

as soon as you set the mode to Follow then the CPU start spiking due to the region updates:

didUpdateUserLocation
regionDidChangeAnimated
regionWillChangeAnimated
didUpdateUserLocation
regionDidChangeAnimated

This point IMHO that the issue is not with the location updates, but with the update of the region in the viewPort

Screenshot 2019-04-29 at 14 49 47

@fabian-guerra
Copy link
Contributor

@racer1988 I did tried with a single coordinate gpx file or fixed location in the simulator. Although I see a spike and I think is normal because the map zooms in, after that it goes to zero. I'm testing the map with the token set.

In my comment #7236 (comment) I posted how using our custom api to simulate updates it's almost unnoticeable.

Thanks for the info I will continue researching. Considering as well if we can try what it was implemented on Android as described in this comment #7236 (comment)

@fabian-guerra
Copy link
Contributor

The intensive CPU usage is due to two main factors:

Location update frequency: Xcode does not allow set a frequency update for gpx files, this can be somehow achieved by adding a timestamp to each location entry per https://stackoverflow.com/a/36416589/1919929. This behavior may be reproducible in an app using a combination of distanceFilter and desiredAccuracy in the default MGLLocationManager, but as is known getting more frequent updates drain the battery, and require more calculations (major cpu usage).

Rendering frequency: As is already pointed in this comment #7236 (comment) updateFromDisplayLink calls our Core GL rendering stack. This stack performs a myriad of calculations leading to the "excessive" cpu usage (even tho you don't provide a token to download the tiles, the calculations are triggered anyways). Although #7125 and #7724 landed a while ago, both are platform level optimizations. It would require a significant change to our render engine to account for a render "cache" mechanism that leads to .

A workaround is change the location update frequency to let the cpu finish the job.

In this pr #14577 I'm exploring another platform level optimization. In the pr I added a point based threshold that will move the camera thus triggering the render engine once the userAnnotationView.center property crossed it.

This is how it looks with a 20point threshold, and using the gpx file. While this optimization seems viable rises questions on if it's worth a lag feeling for camera updates, and how it will behave for followWithCourse.

threshold

In conclusion I suggest change the location update frequency.

@dorthwein
Copy link

Has there been any progress on this? We're running into this with a turn by turn issue (using react-native-mapbox-gl)

@noway
Copy link

noway commented Feb 10, 2020

bump to this. not only user tracking is affected, but [source setShape: shape]; too

@datwelk
Copy link

datwelk commented Mar 30, 2020

Also experiencing crash logs due to excessive cpu usage during turn-by-turn navigation:

Event:           cpu usage
Action taken:    Process killed
CPU:             48 seconds cpu time over 59 seconds (81% cpu average), exceeding limit of 80% cpu over 60 seconds
CPU limit:       48s
Limit duration:  60s
CPU used:        48s
Duration:        7.03s
Steps:           8

@juliopiubello
Copy link

any updated on this?

@developius
Copy link

I'm seeing this in a React Native app too, but interestingly, I'm also seeing the exact same behaviour in a pure SwiftUI app.
On a simulator running either app, as soon as I set tracking mode to follow, the CPU goes through the roof.
I can't reproduce the issue on my iPhone XR so perhaps this is a simulator-only problem? Certainly wouldn't be the first 😤

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Core The cross-platform C++ core, aka mbgl iOS Mapbox Maps SDK for iOS navigation For the Mapbox Navigation SDK for Android or iOS or navigation use cases in general performance Speed, stability, CPU usage, memory usage, or power usage
Projects
None yet
Development

Successfully merging a pull request may close this issue.