Performance: isolate Home preview recomposition, cache category queries, add baseline profiles - #162
Open
amazd wants to merge 4 commits into
Open
Performance: isolate Home preview recomposition, cache category queries, add baseline profiles#162amazd wants to merge 4 commits into
amazd wants to merge 4 commits into
Conversation
Preview playback ticks (loading/error transitions while a stream spins up or stalls) used to republish the entire HomeUiState, recomposing the whole Home screen. Preview state now lives in its own HomePreviewUiState flow, read only inside the new HomeLivePreviewHost composable so playback ticks recompose just the preview pane.
Domain models and java.time types come from modules that don't run the Compose compiler, so they were inferred unstable and forced recomposition of every composable taking them as parameters. compose-stability.conf marks them stable so those composables can skip when inputs are unchanged.
getCategories() runs a GROUP BY aggregate over the whole channels table (50k+ rows on large providers) and re-ran cold on every screen entry. The flow is now shared per provider via shareIn(replay = 1): re-entering a screen renders the last list instantly while Room refreshes it in the background. WhileSubscribed(0) stops the upstream query as soon as the last subscriber leaves so catalog syncs don't keep re-running the heavy aggregate with nobody watching.
New :baselineprofile module (Macrobenchmark + UiAutomator) generates profiles covering app startup and the Home screen hot paths; generated profiles for the release and beta variants are checked in. The profileinstaller dependency installs them at install time so sideloaded builds (Fire TV has no Play Store cloud profiles) get AOT-compiled hot paths instead of cold JIT. Refresh with: ./gradlew :app:generateBaselineProfile
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.
Summary
Three performance improvements targeting Home screen smoothness and cold start, especially on lower-end devices (Fire TV):
HomeUiStateinto a dedicatedHomePreviewUiStateflow, read only inside a newHomeLivePreviewHostcomposable. Playback ticks while a stream spins up or rebuffers now recompose just the preview pane instead of the entire Home screen.compose-stability.confmarks cross-module immutable classes (com.streamvault.domain.model.**,java.time.**) as stable so composables taking them as parameters can skip recomposition; they were previously inferred unstable because :domain doesn't run the Compose compiler.getCategories()runs a GROUP BY aggregate over the whole channels table (50k+ rows on large providers). It is now shared per provider viashareIn(replay = 1), so re-entering a screen renders instantly from replay while Room refreshes in the background.WhileSubscribed(0)stops the upstream query when unobserved so catalog syncs don't keep re-running it.:baselineprofileMacrobenchmark module generates startup + Home hot-path profiles (checked in for release/beta);profileinstallerapplies them at install time so sideloaded builds get AOT-compiled hot paths instead of cold JIT. Refresh with./gradlew :app:generateBaselineProfile.Test plan
🤖 Generated with Claude Code