Deep Dive Into Android Memory
Android app development always reminds us that we are part of the android hardware and operating system.
We can divide Android phones into certain levels in terms of hardware. Basically, we can classify them as entry-intermediate and advanced hardware-API phones. When developing applications, developing at a level that will work on low-level hardware or API means appealing to more users.
We tend to integrate more and more features and technologies into our applications over time, which means increased code maintenance over time and increased demands on hardware memory etc.
The Android OS works on the principle that unused or idle memory is wasted memory. It always tries to use all available space in an optimized way against the needs. If there is enough space, the system continues to hold memory after applications are closed or put in the background. When the user opens the application again, it launches faster. This is why most android devices run with very little free space.
Access is required for the use of memory by software. This is usually accomplished through Linux kernels and drivers. Applications then communicate via interfaces provided by the drivers. The areas can be divided into Virtual memory and Physical memory. The CPU manages RAM using Memory Management.
The Android OS shares between RAM pages to fit everything it needs in RAM. Each application process forks Zygote and starts when the common framework code is loaded when the system boots. This approach allows framework-source code to be shared across most RAM pages. For details see.
Android Devices include Ram-zRam and Storage.
- RAM : Limited in size. Fastest type of memory
- zRam : A section of RAM used for short-term situations. Everything is compressed as it is moved into and out of zRam and decompressed when copied.
- Storage : Contains persistent data. It contains data such as applications, libraries and platform files.
In case there is not enough memory, the android OS takes various precautions. Let’s consider a scenario where multiple applications are running in the background. Android OS activates Garbage Collection-kswapd and Low Memory Killer in stages in the system.
Garbage Collection
Basically, it has two important tasks.
- Finding objects in a program that will not be accessible in the future
- Enabling the system to recover resources used by inaccessible objects
Operating systems keep track of each allocated area of memory and manage operations there. ART and Dalvik are similar. Memory is divided into various classifications depending on the size and length of time the object is held and how long it is held is managed.
In the first stage, objects are transferred to Young and then to Old-Permanent stages. Each object has an upper limit in memory. As the Generation starts to fill up, Android OS runs Garbage Collection. GC runtime varies depending on the number of active objects and size. Most of the time GC is managed by the system. There are methods to interfere with this process but it is not recommended.
Kswapd(Kernel Swap Daemon)
Android OS works with Memory Mapping-Pages. Each page corresponds to approximately 4kb. Pages can be categorized as cache, used and free. Pages can be classified as Clean and Dirty.
- Clean : Unmodified copy of the file in memory.
- Dirty : A modified copy of the file in memory.
Unused pages are the free part of RAM. Pages in use refers to the RAM that is actively used.
Clean pages can be deleted because they can always be recreated using the data. But dirty pages cannot be deleted, otherwise the modified data will be lost.
Kswapd is part of the Linux kernel and converts used memory into free memory. It is triggered when memory reaches a certain level. Kswapd starts reclaiming memory. When enough space is available, the reclaiming process is stopped. Memory is reclaimed by deleting pages or moving them to zRam for compression.
Low Memory Killer
It is called when sufficient memory space cannot be obtained despite precautions. The system uses the onTrimMemory method to notify an application that memory is running low and allocations should be reduced. If it is not enough, the Low Memory Killer is activated. It starts stopping processes with a specific scoring system.
LMK starts killing processes starting from the top of the table downwards. Device manufacturers can change the behavior of LMK. Let’s look at these examples in a complete scenario.
On a low-end device, when the user starts to use multiple applications gradually, garbage collection starts to run as they approach the limit according to the memory used by the applications. When the Android operating system reaches the Kswapd threshold, pages are moved to zRam and compressed or cleaned to free up memory space. In a situation where Kswapd cannot cope, Low Memory Killer comes into play and starts killing applications.
This situation is undesirable and bad for the user. Let’s assume that the user is using application X. At a high memory usage, he put it in the background and switched to application Y. If application X is closed during this time, when he opens this application again, he will wait for a noticeable period of time. This means a loss of time and data for the user when there is an important transaction.
Memory Management
There can be many reasons why our applications use too much memory. Situations that cause Memory Leak, library selection, creation of too many instant objects that are nested or perform large operations, etc. Monitoring tools such as Memory Profiler or Perfetto can be used in Android Studio to detect and debug these.
Memory Leak : Prevents Garbage collection from detecting and recovering unused objects. For this reason, it causes us to operate on less than 100% of the memory.
Library selection : The libraries used in the application have a certain load on the application, from compile or runtime execution to the methods they use.
Application Size : Everything we put in the application (using PNG instead of SVG, etc.) affects the application size. Reducing the APK size significantly reduces memory usage.
Factory Based : Factory structures can be considered in areas where there are objects created in areas where code complexity is high, where there are too many objects or intensive operations.
Object Pool : It can be used if the same type of object is used repeatedly in the application. When the object is not used and will be destroyed, if it needs to be used again in the future, it can be taken from the pool instead of re-creating it when needed by preventing its destruction. This requires good synchronization and usage.
Many external factors affect the memory usage of Android applications. Even with different API lvl of the same devices or different applications and permissions, there may be differences in usage. For this, the system should be well monitored and tested. It is important to pay attention to the memory and lifecycle of applications and to develop in a way that minimizes data loss.
For comments, suggestions or criticisms, you can reach us on LinkedIn or Twitter.