Measuring Dispatch before making it faster
Dispatch is the Android app I’ve been building as one front door to my homelab and my day: the morning brief, my training plan, the house. At work, measuring performance before trying to improve it is standard operating procedure. In my own projects it had never come up, partly because I didn’t have the skills for it to matter, and performance is one of the places AI building tools still need the most steering.
The one speed change on record for Dispatch was from mid-September. On the emulator, median cold start went from 804 milliseconds to 787 across five force-stopped launches. The change behind it moved a background-job library’s setup off the path the app runs before its own code starts, where an overnight build session had spotted about 45 milliseconds in the system log. Those 45 milliseconds never showed up end to end, and five launches on an emulator couldn’t say whether 17 was an improvement or ordinary wobble.
Around then Anthropic published an engineering post on how they made claude.ai about three times faster in two weeks. Reading about how the people who build these tools use them is one of the cheapest ways I know to learn, and this one matched what I was missing. I didn’t borrow their numbers. I borrowed the order of operations: get a baseline you trust, then optimize, then measure again.
So one evening’s performance work went entirely to measurement. Dispatch now times three paths I actually use: opening the brief from the morning notification, coming back to a brief that’s already open, and switching to the Coach tab until its workout table settles. Each run records the total time, which phase took it, and the exact build that produced it, and the rows land in a saved search on my log server. There’s no dashboard. When I want to know how a build did, I ask my AI tools to read the rows and tell me about anything that moved meaningfully. The dashboards can come when there’s something that needs one.
A second measurement runs in a test harness on my development machine rather than on the phone. It counts recompositions: how many times the app’s UI framework reruns a piece of a screen’s code for a single interaction. That count is not a timing, and it doesn’t say how hard the phone works to draw anything. For now I track the count across builds without making it a pass-or-fail gate; I haven’t established whether changes track anything I can feel.
On its first run, it flagged a layout fix merged a few hours earlier. Opening the Coach tab now ran the code for every cell of the workout table twice, 36 recompositions where the baseline had 18, with no visible defect on screen. I had only set out to get a baseline, so having it catch something we had just shipped was a genuine moment of delight. The baseline was re-recorded with the higher count, and a later fix for an unrelated label problem brought it back to 18.
Those numbers have since shaped the first real round of speed work, and the one change checked on my phone so far made no measurable difference, a result I trust far more than the 17 milliseconds.