At work, while finding out what was the cause of our app crashing when rendering polygons on a map, we discovered some profile and debug tools and learnt a flow to successfully debug this kind of problems and understand what’s happening on the backstage of both Android and iOS platforms.
This is how we’re using the tools explained on this guide to find bottlenecks that affect the performance of our react native app.
🍎 How to profile & debug on iOS
On iOS, we only need to run our app from Xcode to the desired device. By selecting the Debug Navigator section, while reproducing the problematic flow from the device, we’ll be able to check the CPU, RAM, energy and so on that the app is currently consuming:
Thanks to this tool, we were able to find out the exact reason of why the app crashed at this point. On this example, our app crashed because of reaching the RAM limit for apps consumption on this device.
As you can see, when we got an error crash, the trace of it is available on the left panel, giving us another hint that the crash was related with rendering Polygons on our map. Moreover, when we click on the error, the full description is shown in red at the top of it.
🤖 How to profile & debug on Android
On Android, we discovered the Profiler, it can be used algongside with Android Studio or in its standalone version.
On MacOS, in order to use the standalone version we need to call it from this route:
On the Profiler, we can check CPU, RAM, Network and Energy. In order to make it work, we need to connect our device to the laptop, click on the + button from the Profiler and select our device. Now, we can reproduce our problematic flow and check what’s happening.
At first, we had problems using the Profiler with some Xiaomi and Huawei devices, getting a crash the first time we clicked a button from the app. We successfully solved it by applying this:
adb shell "run-as <your-app-package> rm -R /data/data/<your-app-package>/code_cache"
Also, we’re able to check on real time, which are the more RAM consuming processes, by clicking on Memory and on the next screen, dragging to the right:
Unlike the Xcode Debug Navigator, on the Profiler we’re not able to see the error crash nor its trace, for that purpose we can use on of these two tools:
It is opened from the terminal by typing:
It will show us all the processes logs from the connected device. As there’s a lot of logs happening, I recommend to save it into a file to check it carefully after the debugging session.
The Flipper tool counts also with logs, in fact, these logs are the same shown from logcat tool. On the other hand, Flipper provides filters and some extra tools to work easier with the whole device logs:
In order to filter the errors and warnings we were interested in, in our case, we used these terms:
- OutOfMemory: If you need to learn more about out of memory error reasons, check this link.
- The app process id
Applying this filtering and then, ordering these logs by time, we were able to follow the whole trace and analyze the whole crashing picture.
💡 The result of profiling and debugging with these tools
Using these tools to monitor what’s happening behind a crashing flow, avoids us wasting time wondering what could it be and helps us providing a truly focused solution to the problem. I think it would be a good habit, at the end of an epic or implementing a set of features, checking the flows with these profilers, this way we’ll take advantage to possible performance problems on the users’ devices and to guarantee a better user experience since the epic release ✨