Please enable JavaScript.
Coggle requires JavaScript to display documents.
App Quality - Coggle Diagram
App Quality
App Preformance
Why app lags
(
link
|
Garbage Collector running too frequently
The time for which GC is running the actual app is not running.
Modern GCs, particularly the one used in ART (Android Runtime), run primarily on background threads to avoid blocking the main thread.
However, short "Stop-The-World" (STW) pauses can still occur during certain operations.
App constantly creates and discards objects. When memory gets tight, the system runs GC to clean up unused objects. While GC is running, your app pauses.
For smooth visuals (60 FPS), an app needs to update its UI every 16ms. If GC pauses the app for too long, it misses these updates, causing skipped frames and noticeable lag.
Memory de-allocation
●
Stack ->
When we exit a method, all the memory allocated in the function is de-allocated.
●
Heap ->
For de-allocating the memory in heap, we have a special agent called
garbage collector
. It runs for certain period intervals of time. When the garbage collector runs and there are no references to the object, the memory gets deallocated.
(
link
)
GC is complex and still requires some brief pauses (STW events) to ensure consistency, especially at critical synchronization points.
While these pauses are much shorter and less frequent than in older, non-concurrent GCs, very frequent object allocation and deallocation can still trigger GC runs that, even with concurrent work, involve pauses long enough to potentially cause frame drops and noticeable lag on the main thread.
Steps to be taken
(Memory Management)
data structures,
variables,
types
Prefer Primitive Types:
Use int, boolean, float, etc., instead of their wrapper classes (Integer, Boolean, Float) to reduce memory overhead and auto-boxing.
Use Efficient Data Structures:
For small, key-value mappings or lists, use ArrayMap and SparseArray instead of HashMap and ArrayList to be more memory efficient.
Use
const val
/
static final
:
Declare constants this way to avoid unnecessary object creation and improve performance.
Minimize Object Allocation:
Avoid creating unnecessary objects. Allocate objects only when needed (use lazy initialization).
reuse resources
Leverage Caching:
Use caching mechanisms like LruCache for Bitmaps to avoid repeated decoding and memory allocations.
Implement Object Pooling:
Reuse objects instead of creating new ones repeatedly, especially for frequently used objects like Bitmaps. Learn about Bitmap pooling.
prevent memory leak
Prevent Memory Leaks:
Avoid holding references to Context (like Activity instances) in long-lived objects (e.g., static inner classes, singletons) to prevent the GC from reclaiming them.
Use static inner classes instead of non-static ones where possible to avoid implicit references to the outer class.
release resources
Release Resources:
Promptly close streams, unregister listeners, and release resources when they are no longer needed.
Doing too much work on the main thread
The main thread is responsible for updating the UI. To keep the UI smooth (at 60 frames per second), it needs to update every 16ms. If a task on the main thread takes longer than 16ms, it blocks the UI from updating.
This blocking prevents the system from drawing the next frame on time, leading to frame drops (= FPS drop). Even a single dropped frame makes animations look choppy and the app feel laggy to the user.
Steps to be taken
(Smooth UI & Responsiveness)
Keeping
the Main Thread
Free
Avoid Blocking Calls:
Ensure no long-running operations block the main thread, which can cause Application Not Responding (ANR) errors.
Offload Heavy Work:
Perform all blocking I/O operations (network calls, database queries, file access) and complex computations on
background threads
(using Kotlin Coroutines, RxJava, ThreadPools, WorkManager, etc.).
UI
Minimize UI Rendering Time:
Ensure each frame is rendered within 16ms (for 60fps). Simplify view hierarchies and drawing logic where possible.
Optimize Layouts:
Flatten your view hierarchy. Use ConstraintLayout to create complex UIs with fewer nested views. Avoid excessive overdraw.