Home » Android » android – Under What Conditions Does ART Compact the Heap?

android – Under What Conditions Does ART Compact the Heap?

Posted by: admin April 23, 2020 Leave a comment

Questions:

One of the touted features of the ART runtime in Android 5.0+ is heap compaction, to reduce heap fragmentation. A fragmented heap can get OutOfMemoryErrors a lot easier, as there may not be a single contiguous free block of memory big enough for your needs, even if the heap overall has enough free space.

I understand that this occurs when the app moves to the background, based on Google conference presentations and the like. However, the only statement that I can find on it in the documentation says:

Homogeneous space compaction is free-list space to free-list space compaction which usually occurs when an app is moved to a pause imperceptible process state. The main reasons for doing this are reducing RAM usage and defragmenting the heap.

It’s unclear exactly what a “pause imperceptible process state” means, technically.

Suppose an app does not have any foreground activities at the moment. Is there anything that the developer might have done that might prevent heap compaction for that app’s process? For example, does having a foreground service block heap compaction?

How to&Answers:

Putting the pieces of the puzzle together.

From what I can determine, ART will compact anything that is paused for 2-3 seconds and by paused it means not currently running in background, so activities, but not running services. It will also compact on the fly, or concurrently while the app is in the foreground.

Currently, the event that triggers heap compaction is ActivityManager process-state changes. When an app goes to background, it notifies ART the process state is no longer jank “perceptible.” This enables ART do things that cause long application thread pauses, such as compaction and monitor deflation.

Chet Hasse states:

Garbage Collection
ART brought improved garbage collection dynamics. For one thing, ART is a moving collector; it is able to compact the heap when a long pause in the application won’t impact user experience (for example, when the app is in the background and is not playing audio). Also, there is a separate heap for large objects like bitmaps, making it faster to find memory for these large objects without wading through the potentially fragmented regular heap. Pauses in ART are regularly in the realm of 2–3ms.

From what I can see any pause in the app is fair game for the ART GC.

I suspect the app needs to be paused completely of all services, etc for the compact to occur, as it’s reallocating the memory addresses of the heap, and for this to occur, it cannot be changing. As this larger compact that is taken during the app pause and not on the fly is a dynamic rearrangement of the heap. The only changes that can be made in the smaller pauses is to re-route some addresses on processes no longer being used.

Though this is an educated guess, not definitive and I will endeavour to get more info.

The source code here should have the answer. They’re using naming like InJankPerceptibleProcessState() and trying to wade through this, as you probably already have yourself.

Reading it, will update answer when/if I find the definite answer.

Answer:

Homogeneous space compaction is free-list space to free-list space compaction which usually occurs when an app is moved to a pause imperceptible process state. The main reasons for doing this are reducing RAM usage and defragmenting the heap.

Source : https://developer.android.com/studio/profile/investigate-ram.html#LogMessages

Answer:

Actually you can measure the idle time of an app by. Start the idle timer and stop if if there is any event captured in TextWatcher/OnKeylistner, if you app is in background and none of these events are called, it is good to be collected by GC.

Also this heap contraction is event based and priority based. Eg if there is never a scenario when user need memory, OS will not even do it.

As far as priority is concerned, for garbage collection, it looks for background apps with no background service, then app with background service and at last the foreground apps.