All docschevron-rightMaps SDK for iOSchevron-rightGuideschevron-rightarrow-leftDebugging and Profilingchevron-rightMapRecorder

MapRecorder

MapRecorder is a utility class introduced in Maps SDK v11, designed to simplify the debugging and profiling process of Map instances. It allows you to record and replay API calls made on a Map instance, making it a valuable tool for enhancing bug reproduction, performance testing, and general development efficiency.

Benefits:

  • MapRecorder minimizes ambiguity in bug reports by automatically capturing essential details like device type, styles, runtime changes, and camera movements.

  • It facilitates performance analysis by recording and documenting API calls during complex camera movements.

Limitations:

  • MapRecorder is designed for development purposes only, and should not be employed in production environments.

  • Recorded sessions can only be reliably replayed in the specific Maps SDK version in which they were initially recorded.

book
NOTE

The MapRecorder class is an experimental feature of Maps SDK v11, which means that the API or the recording format might change in the future.

Debugging with MapRecorder

Bug reports often involve intricate conditions for issue reproduction in a debugging environment, such as specific device types, applied styles, runtime changes (e.g., toggling terrain or projection modes), and camera movements. Historically, these details were manually provided in bug reports, occasionally omitting critical information and causing delays in investigations. MapRecorder automates much of this ambiguity resolution.

Example Scenario: Imagine a customer reporting flickering POI labels at high zoom levels during camera pitch changes—a problem not easily captured with a screenshot due to its dependency on camera movement. The issue report lacks key details, including the SDK version, specific problematic coordinates, and the applied style. But, it includes a video illustrating the problem (see the flickering symbol near the bottom edge).

In situations like this, MapRecorder becomes invaluable for reproducing and resolving the issue. Initialization and session capture examples are available in the Maps iOS SDK GitHub repository.

Capturing the Session: Initiate the capture during the application launch, export the resulting recording, and include it in the bug report. The recording is a compressed JSON file containing session metadata and a sequence of API calls executed on the Map instance.

For the reported issue mentioned above, the following essential fields would be obtained:

"metadata": {
  "mapsCoreVersion": "11.0.0",
  "systemInfoPlatformName": "iOS",
  ...
},
"initialState": {
  "cameraOptions": {
    "center": {
      "lat": 48.8619210154175,
      "lon": 2.3358602219522597
    },
    "pitch": 26.740234375000577,
    "zoom": 19.41503664104012,
    ...
  },
  "projectionName": "mercator",
  "terrainEnabled": false,
  "style": "mapbox://styles/mapbox/standard"
  ...
},
"sequence": [
  ["SetGestureInProgress", true],
  ["PitchBy", -0.123046875],
  ["wait", 1100 ],
  ["PitchBy",-0.267578125],
  ...
]

Some of the values are omitted for readability.

The recorded JSON file contains all the information that was missing before, making it a valuable resource for resolving the issue. Moreover, it can be seamlessly loaded into our development environment to replay the sequence, drastically reducing the time required for investigation. This recorded session can also be repurposed as a unit test to preemptively detect regressions after implementing the fix, ensuring long-term stability.

Performance profiling with MapRecorder

Testing and profiling the performance of a Map can be challenging, particularly when addressing issues related to rendering slowdowns. Several factors contribute to this, including iterative style changes, runtime configuration adjustments, and increased feature density in specific regions. Often, these performance issues manifest only when the camera is actively moved on the map. To effectively compare and address such scenarios, we need repeatable conditions that are consistent.

Example scenario: Imagine a runtime change situation in which a new layer is incorporated into an existing map style. This addition leads to performance degradation on older devices during a navigation session. Specifically, this new layer is introduced to showcase points of interest (POIs) on the map. Due to the constraints of a specific test hardware, noticeable frame drops become visible when the camera is adjusted to a high pitch value and its position changes during the navigation session.

We can leverage MapRecorder to record the initial state and camera movements, in the same way as we did in the debugging example. This recording can then be replayed to visually compare the map's performance with and without the new layer. To assess performance changes, we can measure frame times during playback using tools such as Xcode Instruments leveraging our Tracing API.

First we can see the baseline scenario without the layer:

Then we add the layer, execute the same playback and measure the frame times again:

Assuming we see a 10% increase in frame times on the target hardware due to the increased feature rendering, we can explore optimizations following Mapbox guidelines. In this specific example, an effective improvement may involve applying the distance-from-center expression in the layer's filter property to hide content far from the camera's center when the map is pitched. Further details on this optimization approach can be found: Filter symbols based on pitch and distance

After the changes are applied, we can run the same recording again and profile the session:

Increasing the number of rendered content on the screen inevitably affects frame times, but in this example, we managed to reduce the initial 10% increase to less than 3% by applying optimized filtering. By employing MapRecorder, we can effectively profile complex scenarios, such as continuous camera movement during navigation or rapid zooming across the map, which can often be challenging to test manually.

Was this page helpful?