mapbox / mapbox-maps-ios

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

Location Consumer Taking Up too much Main Thread Space and Lagging Map #1489

Open henryouang opened 2 years ago

henryouang commented 2 years ago

Environment

Observed behavior and steps to reproduce

Do a few calculations that must be on the main thread as you pan the map. The frame rate of the application drops significantly, even while idle.

Expected behavior

No frame rate lag, especially when map is idle.

Notes / preliminary analysis

I have some calculations I need to do on the main thread for manual clustering because that doesn't seem to be supported right now. The problem is, with all these calculations, the frame rates don't make the cut and the lag is non-production ready. Upon further investigation, I found this snippet of code that took up much of my main thread queue in the location consumer in v10.6.1:

extension InterpolatedLocationProducer: LocationConsumer {
    internal func locationUpdate(newLocation: Location) {
        let currentDate = dateProvider.now

        // as a first iteration, assume a 1s location update interval and use a
        // slightly longer interpolation duration to avoid pauses between updates
        let duration: TimeInterval = 1.1

        if let location = interpolatedLocation(with: currentDate) {
            // calculate new start location via interpolation to current date
            startLocation = location
            startDate = currentDate
            endLocation = InterpolatedLocation(location: newLocation)
            endDate = currentDate + duration
        } else {
            // first location: initialize state, no interpolation will happen
            // until the next location update
            startLocation = InterpolatedLocation(location: newLocation)
            startDate = currentDate - duration
            endLocation = startLocation
            endDate = currentDate
        }
    }
}

Looking at my OS log, this function is called many many times within one second and clogging up my main queue. I don't think it is necessary to call it this many times in such a short period of time. This lag is even present when the map is idle. When looking at my CPU usage, there is a ton of activity even when I am not moving the map.

After commenting the above code out, my calculations make the cut and the frame rate is back to normal. I know this is essential to displaying the puck on the map, but can't we limit it rather than call it 10 times a second?

Please let me know what I should do. Thank you.

evil159 commented 2 years ago

Hi @enteleca, thanks for the detailed report! This method is invoked whenever CLLocationManager sends an updated location or heading. If these updates happen to frequently - try setting a distance filter with LocationOptions.distanceFilter.

henryouang commented 2 years ago

Hi @enteleca, thanks for the detailed report! This method is invoked whenever CLLocationManager sends an updated location or heading. If these updates happen to frequently - try setting a distance filter with LocationOptions.distanceFilter.

Hi @evil159, thanks for the response. Upon investigation, I noticed that this was being called on the main queue. To experiment, I switched it over to a background thread and so far everything seems to be running smoothly with significantly improved frame rates. Perhaps we could move locationUpdate onto a background thread? What is a reason we couldn't just move it onto a background thread?

On the topic of the distance filter, that is a great idea, however I would like my location to be as accurate as possible in my situation. Throwing the call on background thread I have found is sufficient for my purposes.