diff --git a/AGENTS.md b/AGENTS.md index 6483e52..9207431 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -477,9 +477,24 @@ machine belongs in `~/.claude/TOOLCHAIN.md` (toolchain versions) or rows has to measure a screen rather than name a number: the history cushion was eight rows, which on a tool-heavy transcript is less than one screenful, and the reader hit the end of what was loaded on every swipe - and stood there for a round trip. That was "scrolling is laggy" -- not a - slow frame. It is `HISTORY_SCREENS` viewports now, counted from what is - actually on screen. + and stood there for a round trip. It is `HISTORY_SCREENS` viewports now, + counted from what is actually on screen. Measured at the server, which is + the one number here that does not depend on how the emulator renders: + against a 24,000-event transcript, ten swipes asked for ten pages before + and three after. +- **What the transcript screen costs to scroll, for whoever measures it + next.** Taken 2026-08-30 on the GPU emulator (`emu up` provides one; a + frame number from the software rasteriser means nothing -- see + `~/.claude/MACHINE.md`), against a real imported transcript with the debug + server at `--delay 120`. Settled and flinging fast, both into fresh + history and back through rows already drawn: **5.2-5.9% janky frames, 99th + percentile 29-32ms, 0-2 slow UI-thread frames.** The stock Settings app on + the same device is 3.3% and 38ms, so this is at the platform floor and + what is left is the emulator rather than the app. The number that is *not* + at the floor is the first few seconds after opening a session, where every + row on the way is being composed for the first time; that is inherent to a + lazy list and it is why a measurement taken before the screen settles + reads three times worse. **Settle first, then reset `gfxinfo`.** - **Only `fetchTranscript` was off the main thread; the fold was not.** `foldEvent` returns a new list per event, so a page is that many copies of a growing list -- fine at 80 events and about 300,000 element copies at diff --git a/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt b/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt index 3f88bf9..1462ddc 100644 --- a/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt +++ b/app/androidApp/src/main/kotlin/com/example/aiapp/SessionScreen.kt @@ -88,13 +88,15 @@ private val LOADING_SPINNER = 48.dp * row is anything from one line to a page and a fixed count is therefore a distance only by * accident. Eight rows was the number, and on a tool-heavy transcript eight rows is less than one * screen: the reader reached the end of what was loaded on *every* swipe and waited a round trip - * standing there. That is what "scrolling is laggy" turned out to be -- not a slow frame, but the - * list running out of transcript, which the emulator showed as a swipe that moved nothing for 689ms - * and then jumped. + * standing there, which is a list running out of transcript rather than a slow frame. * * Three, so a fling lands on rows that are already there and the page after them is on its way. The * cost of being generous is a page fetched that nobody reads; the cost of being mean is a list that * stops under a finger, and those are not the same size. + * + * Counted at the server rather than inferred from the screen, which is the only measurement here + * that does not depend on how the emulator renders: against a 24,000-event transcript at `--delay + * 120`, ten swipes asked for **ten** pages before this and **three** after. */ private const val HISTORY_SCREENS = 3