Warm a fence's highlighting like a parse, and page the restore by rows
Two things the measurements for the previous commit turned up. Highlighting a fence cost 174ms for a two-hundred-line Kotlin block, and the lazy list charged it again every time that block scrolled back into composition -- six times in one bench run, with the scroll's draw phase at 1.29ms per frame. So it is warmed and cached where parses already are: `highlight` is a plain function taking no colour from the theme, `warm` fills `ParsedReplies.highlighted` from `fences(parse)` off the drawing thread, and `fenceContent` extracts the code here rather than through the library's composable, so the string warmed is the string drawn. And the anchor restore asked for a span counted in events, which goes negative when the anchor's row is the oldest half-row and was coerced to one -- a request per delta, six hundred round trips walking one reply back a word at a time with the spinner up. It asks for a page of rows now. Clean pairs, fresh sessions each side, same gestures. Fence scroll (transcript-bench.sh): draw phase 0.74ms per frame before highlighting existed, 0.77ms after, no lexing in the window either side. Streaming forty linked items (stream-bench.sh): 2412ms of reparsing before, 674ms after; mean 5.0ms to 1.4ms, worst 8.9ms to 7.9ms. Bullet glyphs, fence colours, the image links and the reference link checked on the emulator; lint clean on AGP 9.4.0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6892dc7caf
commit
ab6a797941
6 files changed
+344
-148
No files matched your search
@@ -711,14 +711,26 @@ fun SessionScreen(
|
||||
// Raw, not coalesced: this counts events back to a known seq, and a page
|
||||
// measured in rows cannot be counted to a seq. `RESTORE_PAGE_MAX` and the loop
|
||||
// bound it; see [loadOlderPage].
|
||||
val span = oldestSeq - anchor.seq + RESTORE_PAGE_CUSHION
|
||||
if (
|
||||
!loadOlderPage(
|
||||
span.coerceIn(1L, RESTORE_PAGE_MAX.toLong()).toInt(),
|
||||
coalesce = false,
|
||||
)
|
||||
)
|
||||
break
|
||||
val behind = oldestSeq - anchor.seq
|
||||
val loaded =
|
||||
if (behind < 0) {
|
||||
// The anchor's row is loaded but is the oldest half-row, which
|
||||
// [anchorRow] refuses; what completes it is the row before it,
|
||||
// and only a page counted in rows can promise to reach that.
|
||||
// Counted in events, the span here is negative and was coerced
|
||||
// to one: a request per delta, walking a long reply back one word
|
||||
// at a time -- six hundred round trips and a spinner for all of
|
||||
// them, seen 2026-09-03 with an anchor inside a 1,400-delta reply.
|
||||
loadOlderPage()
|
||||
} else {
|
||||
loadOlderPage(
|
||||
(behind + RESTORE_PAGE_CUSHION)
|
||||
.coerceIn(1L, RESTORE_PAGE_MAX.toLong())
|
||||
.toInt(),
|
||||
coalesce = false,
|
||||
)
|
||||
}
|
||||
if (!loaded) break
|
||||
}
|
||||
// Resolved to the row that *holds* the saved position rather than passed
|
||||
// straight through, because the two are not always the same seq: the events
|
||||
|
||||
Reference in new issue
Block a user