Triggered when the size of the heap hits some soft limit.
Triggered when a GC was explicitly requested
FIND ROOT SETS: The GC pauses all the threads in the system to find the root sets. “Root sets” are typically local variables, threads, static variables.
MARK REACHABLE OBJECTS (I): In this phase, the GC marks all the root sets found in the previous phase as reachable, letting the unreachable objects to be collected later. This phase is concurrent. This means that your app is running again, and can allocate new objects.
MARK REACHABLE OBJECTS (II): When a new allocation happens, the GC needs to find all the root sets again, which means pausing all your threads again. This phase is not concurrent so your application start to have little “pauses” that feels like the phone is doing a lot of heavy work.
COLLECT: The GC collects all the objects that have not been marked as live. This phase is concurrent.
ART (Lillipop/Marshmallow)
Objects are classified into “generations”, based in the expected life and size of the object. The objects are inserted into the “Young generation” first. When an object stays active long enough, it can be promoted to an older generation, followed by a permanent generation. Each heap generation have their own dedicated upper limit on the amount of memory that objects there can occupy. When a generation is reaching that limit, the system fires a garbage collection in that generation. This allow the GC to save a lot of time during allocations, because it tries to free up space collecting generation by generation and only if necessary.
Making the 1st phase of the mark-and-sweep algorithm concurrent, reducing the time needed to run the mark-and-sweep algorithm from ~10 ms to ~3 ms.
Group small allocations in chunks and page-aligned large allocations, making it much more performant than before. The reason why page-aligned allocations are possible is because ART does not have the memory constraints that Dalvik had. Dalvik only allowed a process to grow for a total of 36mb in memory.
Replacement of the dlmalloc algorithm for a RosAlloc algorithm. Those algorithms are the ones used when you call malloc in native code or new in, e.g., C++ or Java code. The great thing about RosAlloc is that it is thread-aware, meaning that it is able to do allocations that are specific to a particular thread.
ART (Nougat)
Rewrite the entire Garbage Collector allocations in Assembly code, allowing the allocations to be 10 times faster than KitKat.
ART (Oreo)
Compacts the heap every time GC runs.
Compaction enables thread local bump pointer object allocation: Allocations are 70% faster than in Android 7.0.2
Concurrent Compaction is GC divide the heap into “buckets” (e.g. 256k). When a thread needs memory, the GC gives that thread a “bucket” to allocate the objects. So, the thread can allocate or collect the objects in that bucket, avoiding to lock the entire system to do the work.
If bucket is less than 70% or 75% utilization, it will get collected and the objects in there will be moved to another bucket.
Generational part of the GC was removed, loosing all of that advantages.
ART (Android 10)
Generational GC is back again! Along with all the features of the Oreo version, bringing an even faster Garbage Collector than before.