Zygote
Learning path · You make apps fast

The Performance Engineer

Startup, jank, memory and batteries. The measurement tools, the mechanisms behind them, and the changes that actually move the numbers.

pages
15
estimated
157 min
0%

0 of 15 pages read

157 minutes in total.

Start with “The main thread” →
  1. The main thread

    Every app process has one thread that does everything the user can see. Blocking it is not slow code — it is an unresponsive app, by definition.

    11 minbeginnerthreading
  2. ART: ahead-of-time, then hybrid

    ART began as the runtime that compiled everything at install. It is now a hybrid of interpreter, JIT and profile-guided AOT, shipped as an updatable module — and each swing of that pendulum was a reaction to the previous one's cost.

    12 minnerdruntime
  3. Garbage collection and jank

    A GC pause of 20 ms is a dropped frame. ART's collector history is a fifteen-year attempt to make that number independent of how much memory the app is using.

    11 minnerdruntime
  4. The life of a frame

    From a touch to photons: how one frame moves through the UI thread, the RenderThread, the GPU, BufferQueue, SurfaceFlinger and the display — and why 16.67 ms is the number that governs everything.

    13 minintermediategraphics
  5. HWUI and the RenderThread

    How Android turns a view tree into GPU work: display lists, RenderNodes, the RenderThread that replays them, Skia's backends, and what 'hardware accelerated' actually promises.

    13 minnerdgraphics
  6. Jank, measured

    Jank is not 'a slow app'. It is a specific missed deadline with a specific victim — the user's perception of cause and effect. How to measure it, what causes it, and how to tell which stage is at fault.

    12 minintermediategraphics
  7. Process importance and the OOM killer

    Android kills processes on purpose. The oom_adj score, the importance tiers, lmkd and PSI, and why clearing your recents saves less battery than it looks.

    13 minintermediatememory-power
  8. Memory accounting

    RSS, PSS, USS, private dirty and the shared Zygote pages: why the number in dumpsys meminfo is smaller than the sum of what the process mapped, and which number actually matters.

    12 minnerdmemory-power
  9. Doze and App Standby

    Two different throttles for two different situations: Doze when the device is idle, App Standby when the app is unused. How they interact, why maintenance windows widen, and what still gets through.

    12 minintermediatememory-power
  10. WorkManager internals

    WorkManager looks like a simple enqueue API. Underneath it is a SQLite database, a constraint-aware scheduler and a JobService, and understanding that stack explains why your work did not run when you expected.

    11 minnerdbackground-work
  11. Lab 10 — Perfetto

    Record a system trace on a device, open it in the Perfetto UI, and learn to read tracks, slices, thread states and CPU scheduling without drowning in the timeline.

    10 minintermediatelabs
  12. Lab 11 — App startup

    Measure a cold start three ways — logcat, am start -W, and a trace — and learn why the number you get depends on the method. Then break the start into its phases and find the expensive one.

    11 minintermediatelabs
  13. Lab 12 — Jank

    A janky frame is one that missed its deadline. Learn to see that in a trace, use FrameTimeline to attribute it, and tell the difference between work on the main thread, work on the RenderThread and time spent not scheduled at all.

    5 minintermediatelabs
  14. Lab 13 — Binder and lock contention

    A thread that is blocked is not a thread that is working. Find synchronous Binder round trips in a trace, see the server side of the call, and identify lock contention from the thread state track.

    6 minnerdlabs
  15. Lab 14 — SQL on traces

    Trace Processor turns a trace into a SQLite-like database. Learn the tables and joins, then answer the questions from the last four labs with queries instead of clicks — and save the good ones.

    5 minnerdlabs