The Performance Engineer
Startup, jank, memory and batteries. The measurement tools, the mechanisms behind them, and the changes that actually move the numbers.
- 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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 - 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