Skip to content

perf(player): optimize neighbor lookups for series episodes and live channel surfing - #386

Open
Kimlimp wants to merge 1 commit into
bilipp:mainfrom
Kimlimp:perf/player-neighbor-lookups
Open

Kimlimp wants to merge 1 commit into
bilipp:mainfrom
Kimlimp:perf/player-neighbor-lookups

Conversation

@Kimlimp

@Kimlimp Kimlimp commented Nov 6, 2026 •

Copy link
Copy Markdown

Summary

  • Bounded episode neighbor lookups (Scope A): Replaced unbounded series.episodes relationship traversal in NextEpisodeResolver with targeted LIMIT 1 fetches for both adjacent episode and season boundary transitions.
  • Composite index & backfill: Added composite #Index<Episode>([\.series, \.seasonNum, \.episodeNum]) on Episode and migration covering index Z_Episode_SwiftDataIndexOnBinaryseriesSeasonEpisode in CatalogIndexBackfill to allow direct SQLite index seeks without temporary B-tree sorting.
  • Bounded channel ring cache (Scope B): Added thread-safe RingCache in LiveChannelNavigator (bounded to 6 scopes, max 2,048 entries per scope, < 1 MB memory) invalidated on context saves (ModelContext.didSave / NSManagedObjectContextDidSave). Preserves exact localized collation (COLLATE NSCollateFinderlike), ties, NULL handling, ring wrap, and profile restrictions.

Performance Measurements

Verified on BrowseQueryBenchmarks:

  • Series Episode Resolution (testSeriesEpisodeResolution):
    • Clock monotonic average: 0.570 s -> 0.149 s (~3.8x faster)
    • Peak physical memory: 66.3 MB -> 44.3 MB (22 MB reduction)
    • Physical memory retained: 9.2 MB -> 0.0 MB (zero retained growth)
  • Channel Surf Resolution (testChannelSurfResolution):
    • Clock monotonic average: 6.027 s -> 0.032 s (~188x faster / ~99.5% reduction)
    • Physical memory retained: 0.0 MB

Testing

  • Passed existing unit and contract tests: NextEpisodeResolverTests, LiveChannelNavigatorTests, LiveChannelNavigatorCollationTests, BrowseQueryShapeTests.
  • Added regression tests in NextEpisodeResolverTests covering duplicate episode positions and non-consecutive season gaps.

…navigation)

- Scope A: Replace series.episodes relationship traversal in NextEpisodeResolver with bounded LIMIT 1 fetches. Added composite index on (series, seasonNum, episodeNum) and covering migration in CatalogIndexBackfill to ensure indexed B-tree lookups without temporary sorting.
- Scope B: Implement bounded RingCache in LiveChannelNavigator to avoid repeated channel positional sort and bisection passes on warm navigation while preserving exact SQLite collation, ties, NULL handling, and ring wrap. Invalidate on context saves.
- Benchmark: Episode resolution reduced from 0.570s to 0.149s with zero retained memory growth (peak RSS dropped by 22MB). Channel surf resolution dropped from 6.027s to 0.032s (~188x faster).
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