Skip to content

perf(home): avoid redundant derived rail work and back off paused hero timer - #387

Open
Kimlimp wants to merge 1 commit into
bilipp:mainfrom
Kimlimp:perf/home-idle-work
Open

Kimlimp wants to merge 1 commit into
bilipp:mainfrom
Kimlimp:perf/home-idle-work

Conversation

@Kimlimp

@Kimlimp Kimlimp commented Nov 6, 2026

Copy link
Copy Markdown

Summary

Avoids redundant sorting/mapping of full catalog collections during Home empty-state checks, and backs off hero timer work while the hero carousel is paused or scrolled below the fold.

Root Cause

  1. Derived content emptiness checks: HomeView.isEmpty referenced recentlyWatched.isEmpty and favorites.isEmpty. Evaluating each computed property mapped and sorted the full set of watched/favorite movies, series, and channels across the active playlist just to check for presence.
  2. Paused TV hero auto-advance wakeups: runAutoAdvance() in TVHomeScreen ticked every 50 ms (20 Hz) regardless of whether the hero was below the fold (isPaused), and unconditionally assigned progress = 0 on every tick, causing continuous @Observable writes and main thread churn when browsing lower rails.

Changes

  1. Presence & Emptiness Optimization (HomeDerivedContent.swift):
    • Added HomeDerivedContent.hasRecentlyWatched(...) and HomeDerivedContent.hasFavorites(...) that early-exit on the first matching item with O(1) scans.
    • Guarded row evaluation in homeRow(for:) (hasRecentlyWatched ? recentlyWatched : [] and hasFavorites ? favorites : []), skipping full array generation when rails are empty.
    • Refactored recentlyWatched and favorites generation into HomeDerivedContent to keep HomeView.swift within size limits.
  2. Hero Auto-Advance Backoff (TVHomeScreen.swift):
    • Guarded progress = 0 writes in TVHeroModel to only execute when progress != 0, preventing redundant notifications.
    • In runAutoAdvance(), increased sleep duration to 200 ms while model.isPaused, reducing idle wakeups by 75% when scrolled below the fold.
    • Added .onDisappear { model.isPaused = true } and .onAppear { model.isPaused = zone != .expanded }.
    • Exposed TVHeroModel in #if os(tvOS) || DEBUG so it can be verified via unit tests on simulator hosts.
  3. Tests (HomeIdleWorkTests.swift):
    • Unit tests covering presence check equivalence to full rail arrays.
    • Coverage for parental restrictions, playlist scoping, and live TV inclusion switches.
    • Unit tests for TVHeroModel progress ticking, auto-advance, dwell preservation, and paused state behavior.

Validation

  • HomeIdleWorkTests: 8 / 8 tests passed.
  • Regression suite (HomeLayoutSettingsTests, HomeDownloadsTests, MediaFavoritesTests): 30 / 30 tests passed.
  • Scripts/lint-tool.sh swiftformat and swiftlint: 0 warnings, 0 violations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant