Memory leak in CameraAnimatorsRunner (11.31.1)

Open
#2,448 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
55/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
swift
Domain
performance

Research direction

Start in Sources/MapboxMaps/Camera/CameraAnimatorsRunner.swift: add(_ animator:) appends each onCameraAnimatorStatusChanged subscription to cancelables and nothing prunes them, so entries outlive their animators. Read how AnyCancelable and ClosureHandlersStore interact to find a safe point to drop cancelled subscriptions (the suggested pruning on next add() is one option). Verify with Instruments/leak counts over a simulated navigation run, mimicking the growth of ClosureHandlersStore<CameraAnimatorStatus, ()> described in the report; done means instance counts stay flat over a long run.

Written by the indexing model from the issue text.

Description

auto-triaged bug :beetle: p2

Versions: mapbox-maps-ios 11.31.1 with mapbox-navigation-ios 3.31.1. CameraAnimatorsRunner.swift on main is byte-for-byte the same as in 11.31.1.

In Sources/MapboxMaps/Camera/CameraAnimatorsRunner.swift, add(_ animator:) stores each animator's onCameraAnimatorStatusChanged subscription in the cancelables set. Nothing ever removes it, so every subscription stays alive until the MapView is deallocated, even after the animator itself has been released. The AnyCancelable returned by ClosureHandlersStore.add(handler:) holds a strong reference to the animator's ClosureHandlersStore and its handler, so each animator leaves behind two NSLocks.

During navigation this grows non-stop. In following mode, NavigationCameraStateTransition.update(to:state:) in the Navigation SDK creates 2-6 new animators on every camera update (zoom and padding are animated even when unchanged), about 5 times a second.

Measured: ClosureHandlersStore<CameraAnimatorStatus, ()> instances grew from 132 to 11,645 over about 2,300 s of simulated driving (about 6 MB). AnyCancelable, ObjectWrapper and NSLock grew at the same rate. There was only one CameraAnimatorsRunner the whole time.

Suggested fix: remove a subscription once its animator has been released, for example by pruning the set on the next add() call. This doesn't change how the camera behaves.

Dominant language
Swift
Stars
601
Forks
198
PR merge metrics
No merged PRs in 30d

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from mapbox/mapbox-maps-ios

All issues in mapbox/mapbox-maps-ios

Similar issues

More Swift issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.