# Performance What has been measured, on what, and — explicitly — what has **not** been measured at all. The rule this file exists to enforce comes from the competitive survey: the market leader's top complaint is thumbnails that load late, its own support reply to a speed complaint was *"your SD card is slow"*, and the lesson recorded there was to measure what was measured and never close a performance complaint by blaming the hardware. Until this file existed, the app had **no performance number of any kind**. ## Cold start | build | device | runs (ms) | median | |---|---|---|---| | debug, `1.0.0-debug` | Xiaomi phone, Android 15 | 1 758 · 1 773 · 1 814 · 1 926 · 2 043 | **1 814 ms** | Taken with `./tools/measure-startup.sh 5`: `am start -W`, and one warm-up start discarded because the first launch after an install pays for dexopt and folding that into a median is how a baseline gets written that nothing can meet. The debug build is deliberately the *slow* case — StrictMode on, LeakCanary attached, no R8 — so this is an upper bound rather than what a user sees. **The release number is the one worth publishing, and it has not been taken yet.** Until it is, no speed claim belongs in the README or the store listing. ### What StrictMode found on the first cold start The same debug build now logs StrictMode violations, and the first cold start produced five, against a 1 814 ms start: | duration | where | ours? | |---|---|---| | 492 ms | `BrowserViewModel.Factory` → `app.cacheDir` | **yes** — `Context.getCacheDir()` checks and creates the private cache directory while the view model is being created, on the main thread | | 397 ms | `BrowserViewModel.rootsOf` → `StorageProvider.space` → `VolumeRepository.stat` | **yes** — free space for every volume is read with `StatFs` inside `refresh()`, which the screen calls from a `LaunchedEffect` | | 477 ms | `FileManagerTheme` → `typography = FileManagerTypography` | no — the platform loading its own typefaces on first composition | | 54 ms × 2 | `miui.util.font.FontSettings` via `MainActivity.onCreate` | no — the OEM's font hook doing `File.exists` while the activity is created | That is **~1.5 s of main-thread disk I/O inside a 1.8 s start**, of which **~0.9 s is ours**. Both of ours are mechanical to move and neither is fixed yet: the cache directory is only needed when a preview copies something, and the free-space line on the roots screen can arrive a frame later. They are the first items of the speed work. ## Not measured yet, and why | number | how it would be taken | why it is not here | |---|---|---| | Folder open, 1 000 / 5 000 / 20 000 files | macrobenchmark `StartupTimingMetric` over a fixture volume, or `TraceSectionMetric` around the listing | needs a `:benchmark` module and a profileable build installed under the **release package id**; on this MIUI phone the first install of a new package id waits for a confirmation dialog, so it cannot run unattended | | Thumbnail paint while scrolling a photo grid | `FrameTimingMetric` | same | | Keystroke → search result | `TraceSectionMetric` around the query and the index read | same | The module does not exist yet, deliberately: half-configured build wiring that nobody can run is worse than an honest gap. It is the next measurement step, and it belongs with the baseline-profile work, which needs the same module. ## What is measured instead, meanwhile The gate measures things that are not latency but do not rot: the test count, lint, detekt against its baseline, and whether `docs/CODE_MAP.md` still matches the tree. Those are the numbers that can be kept true by automation; the three above need a device and a decision about which device. ## Two rules - **No number that was not taken from a real build on a real device.** Not from a debug build pretending to be release, and not from reading the code. - **No performance change judged by reading the code.** The bigger-thumbnail change (28 → 48 dp in a row, 40 → 96 dp in a grid) is the standing example: it may be exactly right, and nobody measured either side of it. `docs/COMPETITIVE_ANALYSIS.md` had already written "a thumbnail that is bigger and slower is strictly worse than one that is smaller and instant" — which is a hypothesis until it is a number.