Skip to main content
2026-09-23PurePlayerPerformanceLarge Libraries

PurePlayer Read Mirror Benchmarks: Sub-Second Deep Paging Across 500,000 Tracks

PurePlayer introduces a dedicated read-only SQLite mirror for massive libraries. In a 500,000-track test environment, deep paging drops to under one second and A-Z index jumps complete in single-digit milliseconds. Initial index creation takes approximately 30 minutes and requires about 2GB of local storage, with full user control in Settings.

PurePlayer Read Mirror Benchmarks: Sub-Second Deep Paging Across 500,000 Tracks

When a local music library reaches hundreds of thousands of songs, the initial screen typically scrolls smoothly, while deep pagination, letter navigation, and global searches experience significant latency. Using a 500,500-track benchmark dataset, we measured query durations across core read paths and introduced a local read-only mirror mechanism planned for version 7.0.

Release note: Version 6.0 introduced initial performance enhancements. The high-performance read mirror detailed here is planned for version 7.0 and is currently in internal testing. All metrics are collected from internal development builds.

The architecture generates a derived read-only SQLite copy of the library locally. Precomputed sort keys, filter attributes, and A-Z index anchors are written to disk during index creation. Primary storage retains canonical data authority, while the read-only mirror handles query workloads and supports independent rebuilds and cleanup on demand.

Benchmark Results

Measurements were conducted on an M4 Mac mini using the 500,500-track dataset, with all queries validated by field-level consistency assertions:

Read path Scale SwiftData Mirror Speedup
Song list snapshot build 10k 3030 ms 21 ms ~143×
List paging (filtered) 10k 1984 ms 8.2 ms ~242×
A-Z anchor jump 10k ~2050 ms 0.4–7.6 ms 274–5100×
Deep page (offset 450k) 500k ~28 min/page ~0.9 s ~1800×
“Any visible rows?” zero-hit scan 100k 98.1 s 46 ms ~2100×
Smart-playlist multi-condition candidates 100k 6.9 s 1.27 s ~5.4×
Playlist page / artist drill-down / first paint 50k – – 4.5–7.3×

At 500,000 tracks, the native read path relies on sequential full-table scans, with execution time scaling with offset depth: fetching a single page near track 400,000 took approximately 1,668 seconds. The read-only mirror reduces query duration at that depth to between 0.8 and 1.4 seconds, maintaining consistent performance regardless of offset distance.

Sort Tags and View Compatibility

For classical and jazz collections, listeners often enable sort tags to organize “The Beatles” under “B” (filed as “Beatles, The”). The mirror materializes two distinct sort key sets for the five tag-aware fields. Enabling or disabling sort tags selects the corresponding column directly in SQL queries, keeping the A-Z index in sync without index regeneration.

Album, artist, and composer aggregation views also leverage mirror queries. When sort tags are active in aggregation views, queries route to the primary storage path to ensure accurate entity-level tag mapping. Write-side materialized aggregation tables are scheduled for future releases to extend mirror acceleration to this scenario.

Resource Overhead and Tradeoffs

Operating a local read mirror involves distinct storage and index creation tradeoffs:

  • Build Duration: Full index creation runs as a background task. Initial indexing for 500,000 tracks took approximately 32 minutes while standard library browsing remained active; a 50,000-track library completes in approximately 35 seconds.
  • Disk Usage: The 500,000-track mirror occupies approximately 2.1GB of local storage. The Settings interface displays actual footprint metrics, and disabling high-performance mode preserves index files for immediate reactivation while offering a complete purge option.
  • Write Overhead: Metadata updates write synchronously to the mirror, adding approximately 20ms per batch commit in our benchmarks.

Because of these resource characteristics, the feature remains disabled by default, allowing users to enable it based on library scale.

Core Optimization Mechanisms

  • Lightweight Value Mapping: The native path instantiates managed object graphs for each row. The mirror reads raw SQLite columns and projects lightweight value types, minimizing object lifecycle overhead.
  • Predicate Pushdown: Filter expressions, sort definitions, and deduplication logic execute directly within the database engine, pruning data prior to memory ingestion.
  • Precomputed Sorting and Indexing: Normalized sort keys and A-Z section letters are calculated during indexing. Runtime retrieval pairs keyset pagination with index scans, securing steady response times on deep pages.

Consistency and Implementation Details

To verify query parity between the mirror and primary storage, the test suite exercised permutations of 19 sort columns, ascending and descending directions, sort tag states, and compound filter conditions. Several implementation details required explicit handling:

  • Null Coalescing and Blank Strings: Sort tags prioritize the tag value and fall back to the display name when absent. Swift optional coalescing evaluates nil, while SQL string functions handle empty strings differently. The mirror materializes tag keys and display keys into separate columns and selects them explicitly during query construction.
  • Field Ordering Compatibility: Track duration in existing libraries is evaluated via lexicographical string comparison (placing “120.0” before “90.0”). To preserve existing behavior, text-based columns materialize dedicated text sort keys, reserving numeric indexes for true numeric attributes.
  • Whitespace Character Set Alignment: Swift whitespace definitions (including full-width spaces, tabs, and newlines) differ slightly from standard SQL trimming functions. A dedicated write-side status flag normalizes emptiness checks across both runtime layers.
  • Chunked Background Processing: At 500,000 rows, full-text triggers perform multi-index writes, bringing total build time to approximately 32 minutes. The build routine executes in resumable chunks to maintain steady background execution.
  • Concurrent Write Arbitration: When metadata modifications occur during an active rebuild, every update attaches a monotonic sequence counter, allowing database conflict handlers to enforce update order accurately.

Benchmark figures reflect debug build metrics; detailed performance traces and reproduction harnesses are archived in the repository.