Android Performance monitoring [Part 1]
Let’s face it, we all know how to write android apps and are good at it. But software development is more complex than what we think.
from android docs:
Putting pixels on the screen involves four primary pieces of hardware. To greatly simplify, the CPU computes display lists, the GPU renders images to the display, the memory stores images and data, and the battery provides electrical power. Each of these pieces of hardware has constraints; pushing or exceeding those constraints causes your app to be slow, have bad display performance, or exhaust the battery.
To discover what causes your specific performance problems, you need to take a look under the hood, use tools to collect data about your app execution behaviour, surface that data as lists and graphics, understand and analyse what you see, and improve your code.
In this part, we will be covering various memory optimisation tools, Let’s get started.
Used to detect memory leaks in an app. A memory leak is when an activity/fragment is destroyed but a reference to it is still alive causing the whole view hierarchy to be in memory when not needed. It is the tool easiest to use , just declare dependencies in Gradle file, add code to your application class as mentioned at LeakCanary Readme and done. LeakCanary will automatically show a notification when an activity memory leak is detected in your debug build.
Now things get a little interesting, there may be no memory leaks in an app, but we still need to check whether our code is running as expected and we are not wasting a single byte of RAM. where is the memory being allocated? what part of code takes more RAM? can we trade off that memory by any choice? is the memory being freed up on time?
I strongly suggest going through Investigating Your RAM Usage in android docs before proceeding further, as we are going to use those tools to analyse our app.
I will be using my Popular Movies app to profile using below tools.
Analysing Heap Dump
We opened the app, browsed different screens and then collected a heap Dump by clicking icon shown below:
And the heap looks like:
Deductions based on the heap:
- we can clearly see that most of our heap consists of bitmaps, as we are displaying images, so in order to decrease memory usage in older devices, we might want to look into decreasing bitmaps resolution.
- Another good observation from this is also that Picasso, an image loading library is using an LRUCache to cache those images and is in singleton pattern by default. (count = 1)
We get the basic idea of what is costly on memory and what is cheap.
Replacing Class list view with package tree view, we can see memory usage by each package. which can help us in deducing whether our coded classes or a 3rd party library classes are the cause of memory usage?
Here we can again see that bitmaps and graphics are taking a lot of memory. size/count ratio is HUGE.
Memory Allocation Tracker
Android Monitor allows you to track memory allocation as it monitors memory use. Tracking memory allocation allows you to monitor where objects are being allocated when you perform certain actions. Knowing these allocations enables you to adjust the method calls related to those actions to optimise app performance and memory use.
Please go through the Allocation Tracker in android docs to see how to collect data using the GUI, and capture one yourself, we’ll use it to analyse and make deductions further in this article.
After capturing the allocation dump, we end up with a Sunburst chart, but how do we read it? what does it mean?
We can group sunburst chart is two ways:
- by method - where we can see the allocations per method.
- by allocator - where we can see the allocations by allocating classes.
The innermost circle is the root of allocation. (thread if grouped by method, package if grouped by allocator. ) and the outermost circle is where the allocation actually happens. Each circle consists of various arcs, the relative size of an arc determines the size of allocation(memory used) or count of allocations; depending on what’s selected by the viewer.
The sunburst can also be replaced by layout chart which works the same way except it’s in bar form instead of circular.
To investigate further we can double-click on any arc and see the sub-allocations with paths inside that part. to go back to the root chart, double-click anywhere outside it.
We can again see that the biggest outermost circle contains bitmaps. i.e Bitmaps are bad for memory.
These deductions are based on my specific app and may vary, the main purpose of this article is to enable devs to monitor and improve their code based on the scenario, how you fix a problem is up to you.
Observing the heap dump is not very easy but practice make a man perfect, you’ll get the hang of it if you do it quite often, made another good observation? be sure to let me know in the comments down below.
Thanks for reading this article. Be sure to click ❤ below to recommend this article if you found it helpful. It would let others get this article in search and spread the knowledge.