perf: stop the freeze on huge conversations and speed up filtering#19
Merged
Merged
Conversation
3b5f044 to
1084a1f
Compare
Navigating to a huge conversation (the top/bottom of a result set can be a 6k-message session) froze the UI - holding a nav key at a list boundary queued frames that each took ~65ms, dominated by formatListItem recomputing the HITS count by scanning every message of every visible row (with a strings.ToLower allocation per message) on every frame. Measured on a 6016-message conversation with 8 big rows visible: View was 65ms/frame; with these caches it's 4.7ms/frame. - Memoise hit counts per query, keyed by SessionID (hitCounter), so formatListItem reads a cached count instead of rescanning each frame. - Memoise the selected conversation's preview lines, keyed by SessionID+query (previewCache), so renderPreview / maxPreviewScroll don't rebuild every frame. Both caches are pointer-held so they survive the value-receiver copies View makes, and both invalidate when the query (or selection) changes.
1084a1f to
069f031
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three hot-path optimisations, all measured on the real corpus (314 conversations). Stacked on #18 (mouse-leak) - merge #18 first.
1. The freeze: memoise HITS per query
Scrolling to the very top/bottom of a result set froze the UI for seconds when a huge conversation (a 6,000-message session) sat at that boundary. Measured: the dominant per-frame cost is
formatListItemrecomputing the HITS count by scanning every message of every visible row (with astrings.ToLowerallocation per message) every frame. Holding a clamped nav key queued those slow frames into a long freeze.hitCountermemoises hit counts per query, keyed by SessionID.View: 65ms → 4.7ms/frame (8 big rows visible).2. Memoise preview lines
previewCachememoises the selected conversation's preview lines (keyed by SessionID+query) sorenderPreview/maxPreviewScrolldon't rebuild every frame. (buildPreviewLineswas ~8ms - not the freeze, but still wasteful every frame.)3. Incremental filtering
updateFilterscanned all 314 conversations'searchLowerevery keystroke (~10ms for a long, rare query). When the new query contains the previous one, every new match already matched the old query, so it now filters the previous (smaller) result set. Steady-state narrowing: ~10ms → ~1-2ms/keystroke.Caches
Both caches are pointer-held so they survive the value-receiver copies
Viewmakes, and invalidate when the query (or selection) changes.Tests
TestHitCountCachedPerQuery,TestPreviewLinesCachedUntilSelectionOrQueryChanges- cached values returned without rescan; invalidate on change.TestUpdateFilterIncrementalNarrowing- narrowing/broadening/clear all produce correct results.go test,go vetgreen; coverage 63.4%.