Profiling a mobile application enables developers to identify whether or not an app is fully optimized (i.e., effectively using resources like memory, graphics, CPU, etc.). If the app is not optimized, it will experience performance issues like memory crashes and slow response times. However, profiling a mobile app seems to be easier said than done. Every mobile platform offers tools that are very well evolved — and still evolving — to provide profiling data that can be analyzed to identify problem areas. In this blog, we’ll look at which parameters to profile, and where to profile these parameters. If you are interested in learning more about how to profile these parameters, I suggest you review the platform-specific documentation below:
Android: https://developer.android.com/ studio/profile
iOS: https://help.apple.com/instruments/mac/ current/#/dev7b09c84f5
Parameters to Profile
The parameters to be profiled are dependent on the unique problem. For example, if the problem is slow UI rendering, a potential area to look is CPU usage and GPU rendering. On the other hand, if the problem is an unresponsive application over a period of time, it indicates potential memory leaks. If the problem is unknown, then you can do application profiling for the following parameters:
- CPU Usage: to identify potential threads and methods that are taking a greater CPU time-slice than expected
- Memory Utilization: to identify potential classes/variables that are holding up the memory
- UI profiling: to identify the potential overdrawing and redrawing of UI components, unoptimized usage of widgets, and deep hierarchy views
- Battery Usage: to identify potentially unnecessary running processes that are drawing current from the battery
- Network Usage: to identify potentially unnecessary network calls or network calls that are taking too much time or downloading heavy data and impacting the user experience
- I/O operation: to identify potential unoptimized or unnecessary file or database operations
Where to Profile
Identifying the areas to be profiled (i.e., screens, features) is the most critical step, as it varies from application to application. If the problem is known, then the area to be profiled can be narrowed down to a particular screen or feature. But if the problem is unknown, then the only option remaining is to profile the complete application. Since most modern applications have many screens and features, you should target specific areas of the application to profile first.
Start of the Application
The start of an application is a very important part where lots of initialization and resource allocation is done. An area to watch out for is CPU consumption for initialization, which can be done in parallel or can be initialized later in the required screen or feature. In a modern application where dependency injection tools like dagger 2 (Android) or Typhoon (iOS) are used, there is every chance that there has been an unnecessary allocation of memory for the injected classes.
Loading of the Screen
Similar to the start of the application, individual screens may have allocated additional resources that are not required. The time required for loading the screen should also be watched, as unnecessary initializations may be blocking the UI rendering. Depending on what needs to be initialized, you should check whether it can be done in a later stage after the UI rendering.
Loading of Scrollable Views
In the mobile form factor, it is common for applications to have screens with scrollable items. There is every chance that standard guidelines for creating scrollable views may not have been followed, resulting in heavy memory consumption that needs to be identified. Also, the slowness in loading items needs to be looked into, as patterns like lazy loading may not have been followed.
A UI-heavy screen needs to be focused, as it may have unoptimized layouts or a deep hierarchy view. Responsiveness should also be checked, as a UI-heavy screen may have an equally heavy backend handling code that may take longer to respond.
Navigation Between Screens
The most common operation done on a mobile application is navigating between screens. As such, you should make sure that resources are being properly allocated and deallocated when navigating between screens. Also, navigation between screens is a potential candidate for a leakage of references, which links to memory leakage.
Peaks in network operations should be reviewed, as heavy network operations can impact the user experience and also lead to heavy CPU and memory usage. Heavy network operations can be broken into smaller logical operations, so unnecessary network operations should be watched.
On many occasions, repetitive operations lead to heavy memory leaks. These repetitive operations can be a scrolling of list items, getting data from the network operations, loading a UI-heavy screen, or navigating between screens.
Keeping the Application Idle for a Long Duration
Ideally, when an application is kept idle for a long duration, it should not increase memory consumption over time. However, the background operation may not be pausing properly, or resource allocation may still be in progress — which can lead to a memory leak.
File logging in release builds should be monitored, as an application may be doing additional/unnecessary file logging, which is an I/O operation. You should also look into the log file rotation policy, as over time it can consume memory in the file system.
Some of the above profiling activities can be achieved using the tools provided by the mobile platform (i.e., Android, OS), while some require manual efforts or code analysis. The ultimate objective of mobile app profiling is to consider the various parameters that could potentially lead to performance problems within your mobile app.