Measure how opening a folder scales, with the phone as the fixture host
The same benchmark against 1000, 5000 and 20000 files, changing only the fixture: 12-14 frames, 41 frames, 184 frames. That is roughly linear, which is what a RecyclerView fed a pre-sorted list should do, and it is the shape to keep watching - a superlinear jump would mean per-row work that belongs to the folder. The number worth keeping an eye on is not the median but the maximum at 20000: 598 frames against a median of 184, so one iteration of five stalled at roughly three times the others. At that size the first open is occasionally not just slow but stuttering, which is exactly the case a release should be checked against. PERFORMANCE.md records the cost of the fixture too, because it dwarfs the measurement: 20000 files took about thirty minutes through MIUI's storage layer against four minutes of benchmark, which is an argument for building the fixture once and keeping it. And it records where the jank metric came from, since this phone cannot produce one: the API 35 emulator at the 1000-file point gave frameDurationCpuMs P50 218 ms and frameOverrunMs P50 315 ms, software-rendered and therefore not comparable, but proof that the metric exists.
This commit is contained in:
@@ -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
|
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.
|
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
|
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
|
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
|
`Ignore()` nothing reinstalls the app between iterations, so the *next* iteration found a search field
|
||||||
|
|||||||
Reference in New Issue
Block a user