diff --git a/docs/PERFORMANCE.md b/docs/PERFORMANCE.md index 702b3d5..935d21c 100644 --- a/docs/PERFORMANCE.md +++ b/docs/PERFORMANCE.md @@ -123,6 +123,34 @@ lasted. It says the interaction is short (14 frames is about a quarter of a seco say whether any of those frames was slow. A device that reports frame durations — an emulator or any non-MIUI phone — is what turns this into a jank number. +### How it scales with folder size + +The same test, run against folders of different sizes on the phone — only the fixture changed +(`./tools/benchmark-fixture.sh --count N`): + +| files in the folder | frames to open it (`openAFolderOfAThousandFiles`) | +|---|---| +| 1 000 | **12–14** (two runs) | +| 5 000 | **41** | +| 20 000 | **184** (min 166, **max 598**) | + +The shape is roughly linear, which is what a `RecyclerView` fed a pre-sorted list should do: five times the +files cost 3.5 times the frames, four times the files cost 4.5 times. A superlinear jump here would mean the +listing had started doing per-row work that belongs to the folder as a whole. + +The **max of 598 at 20 000** is the number to keep an eye on. The median says the folder opens in about +three seconds' worth of frames; one iteration of five took three times that, so at that size the first open +is not merely slow but occasionally stalls — worth watching rather than explaining away, and the reason the +20 000 point is the one a release should be checked against. + +Building that fixture is the expensive part, not measuring it: 20 000 files took about thirty minutes +through MIUI's storage layer (`: >` in a loop), against roughly four minutes of benchmark on top. Worth +knowing before anyone re-creates it, and an argument for the fixture being built once and kept. + +The emulator supplied the jank *metric* this phone cannot, at the 1 000-file point: `frameDurationCpuMs` +P50 218 ms, P90 330 ms, and `frameOverrunMs` P50 315 ms. Software-rendered, so the values are not +comparable with the phone's — what they prove is that the metric exists where frame timelines exist. + One bug had to be fixed before `search` could be measured, and it is worth knowing about because it looked like a UI problem and was a state problem: the search iteration ends with search mode open, and with `Ignore()` nothing reinstalls the app between iterations, so the *next* iteration found a search field