Zum Hauptinhalt springen
2026-09-23PurePlayerPerformance-MessungGroße Bibliotheken

PurePlayer Lesespiegel im Benchmark: Deep Paging bei 500.000 Titeln unter einer Sekunde

PurePlayer führt eine dedizierte schreibgeschützte SQLite-Spiegelschicht für große Musiksammlungen ein. In einer Testumgebung mit 500.000 Titeln sinkt die Antwortzeit für Deep Paging auf unter eine Sekunde, während A-Z-Indexsprünge im einstelligen Millisekundenbereich abschließen. Der initiale Indexaufbau benötigt rund 30 Minuten und etwa 2 GB lokalen Speicherplatz und lässt sich in den Einstellungen verwalten.

PurePlayer Lesespiegel im Benchmark: Deep Paging bei 500.000 Titeln unter einer Sekunde

Umfasst eine lokale Musikbibliothek mehrere hunderttausend Titel, bleibt das Scrollen auf der ersten Anzeigeseite meist flüssig, während tiefes Blättern, Buchstabensprünge und globale Suchen spürbare Latenzen verursachen. Anhand eines Referenzdatensatzes mit 500.500 Titeln haben wir die Ausführungszeiten zentraler Lesepfade gemessen und für Version 7.0 einen lokalen schreibgeschützten Spiegelmechanismus entwickelt.

Versionshinweis: Version 6.0 enthält grundlegende Performance-Optimierungen. Der hier beschriebene Hochleistungs-Lesespiegel ist für Version 7.0 vorgesehen und befindet sich in der internen Testphase. Alle Messwerte stammen aus internen Entwicklungs-Builds.

Die Architektur erzeugt lokal eine abgeleitete, schreibgeschützte SQLite-Kopie der Bibliothek. Während des Indexaufbaus werden Sortierschlüssel, Filterattribute und A-Z-Indexanker vorberechnet und dauerhaft auf der Festplatte gespeichert. Der primäre Systemspeicher behält die Datenhoheit, während der Lesespiegel Abfragen bedient und sich bei Bedarf unabhängig neu aufbauen oder bereinigen lässt.

Gemessene Benchmark-Ergebnisse

Die Messungen erfolgten auf einem M4 Mac mini mit dem Datensatz über 500.500 Titel; alle Werte wurden über feldweise Konsistenzprüfungen validiert:

Lesepfad Umfang Primärspeicher Spiegel Beschleunigung
Aufbau des Titellisten-Snapshots 10k 3030 ms 21 ms ~143×
Listen-Paging (gefiltert) 10k 1984 ms 8,2 ms ~242×
A-Z-Ankersprung 10k ~2050 ms 0,4–7,6 ms 274–5100×
Tiefe Seite (Offset 450k) 500k ~28 Min./Seite ~0,9 s ~1800×
Null-Treffer-Scan „Sichtbare Zeilen vorhanden?" 100k 98,1 s 46 ms ~2100×
Mehrfachkriterien für Smart-Playlists 100k 6,9 s 1,27 s ~5,4×
Playlist-Ansicht / Künstler-Detail / Erstaufbau 50k – – 4,5–7,3×

Bei 500.000 Titeln nutzt der ursprüngliche Pfad vollständige Tabellenscans, sodass die Ausführungszeit mit steigendem Offset stark zunimmt: Das Laden einer einzelnen Seite um Titel 400.000 dauerte als Baseline rund 1668 Sekunden. Der schreibgeschützte Spiegel senkt die Abfragedauer an dieser Stelle auf 0,8 bis 1,4 Sekunden und hält die Zugriffszeit über unterschiedliche Tiefen stabil.

Sortier-Tags und Ansichtenkompatibilität

In Klassik- und Jazzsammlungen aktivieren Hörer häufig Sortier-Tags, um Interpreten wie „The Beatles" unter dem Buchstaben B („Beatles, The") einzuordnen. Der Spiegel hinterlegt für die fünf tag-fähigen Felder jeweils zwei getrennte Sortierschlüssel. Beim Umschalten der Sortier-Tags wählt die Abfrage direkt die entsprechende Spalte aus, wodurch die A-Z-Leiste synchron bleibt, ohne dass der Index neu erzeugt werden muss.

Auch Aggregationsansichten für Alben, Interpreten und Komponisten nutzen Spiegelabfragen. Sind Sortier-Tags in diesen Ansichten aktiv, schaltet das System auf den primären Speicherpfad um, um die exakten Tag-Werte auf Entitätsebene abzubilden. Schreibseitig materialisierte Aggregationstabellen sind für künftige Versionen vorgesehen.

Ressourcenbedarf und Abwägungen

Der Betrieb des lokalen Spiegels erfordert zusätzliche Zeit für den Indexaufbau sowie lokalen Speicherplatz:

  • Aufbaudauer: Die vollständige Indexerstellung erfolgt als Hintergrundprozess. Für 500.000 Titel benötigt der erste Aufbau rund 32 Minuten, während die Standardnavigation uneingeschränkt nutzbar bleibt; 50.000 Titel sind in etwa 35 Sekunden verarbeitet.
  • Speicherbelegung: Die Spiegeldatei für 500.000 Titel belegt rund 2,1 GB Speicherplatz. Der genaue Verbrauch wird in den Einstellungen ausgewiesen. Bei Deaktivierung bleibt der Index für eine spätere Wiederaufnahme erhalten; eine vollständige Bereinigung ist ebenfalls möglich.
  • Schreiblatenz: Änderungen an Titel-Metadaten werden synchron in den Spiegel übertragen, was in Tests rund 20 Millisekunden pro Batch-Commit beansprucht.

Aufgrund dieses Ressourcenprofils bleibt die Funktion standardmäßig deaktiviert und kann in den Einstellungen gezielt für umfangreiche Bibliotheken zugeschaltet werden.

Zentrale Optimierungsmechanismen

  • Leichtgewichtige Wertprojektion: Während der reguläre Pfad verwaltete Objektmodelle instanziiert, liest der Spiegel Rohzeilen direkt aus SQLite und bildet sie auf schlanke Werttypen ab, was den Verarbeitungsaufwand im Lebenszyklus minimiert.
  • Prädikat-Pushdown: Filterkriterien, Sortierlogik und Deduplizierung werden direkt in der Datenbank-Engine ausgeführt, wodurch Datenmengen vor dem Laden in den Arbeitsspeicher reduziert werden.
  • Vorberechnete Sortier- und Indexschlüssel: Normalisierte Sortierschlüssel und A-Z-Buchstabenanker werden beim Indexieren festgeschrieben. Abfragen kombinieren Keyset-Paginierung mit Index-Scans und halten die Antwortzeit auch bei tiefen Seiten konstant.

Datenkonsistenz und Implementierungsdetails

Um die Übereinstimmung der Abfrageergebnisse zwischen Spiegel und Hauptspeicher sicherzustellen, deckt die Testsuite Permutationen aus 19 Sortierspalten, Sortierrichtungen, Tag-Status und kombinierten Filtern ab. Im Zuge der Angleichung wurden mehrere Randfälle adressiert:

  • Null-Werte und leere Zeichenketten: Sortier-Tags priorisieren den Tag-Inhalt und greifen bei Fehlen auf den Anzeigenamen zurück. Da Swift-Operatoren und SQL-Funktionen leere Zeichenketten unterschiedlich auswerten, materialisiert der Spiegel Tag- und Anzeigeschlüssel in separaten Spalten und wählt diese bei der Abfrageerstellung explizit an.
  • Sortierkompatibilität historischer Felder: Titellaufzeiten wurden historisch per Zeichenkettenvergleich sortiert (beispielsweise „120.0" vor „90.0"). Um bestehende Abläufe nicht zu verändern, erhalten textbasierte Spalten dedizierte Textsortierschlüssel, während numerische Indizes echten Zahlenwerten vorbehalten bleiben.
  • Definition von Leerraumzeichen: Da sich die Definitionen von Whitespace in Swift und standardmäßigen SQL-Trim-Funktionen leicht unterscheiden, synchronisiert ein statusbasiertes Flag auf der Schreibseite die Auswertung beider Schichten.
  • Segmentierter Hintergrundaufbau: Bei 500.000 Datensätzen führen Volltextsuch-Trigger zu mehrfachen Indexschreibvorgängen, was die Gesamtdauer auf rund 32 Minuten erhöht. Der Aufbauprozess ist segmentiert aufgebaut und unterstützt das Fortsetzen nach Unterbrechungen.
  • Koordination paralleler Schreibvorgänge: Werden während eines aktiven Indexaufbaus Metadaten bearbeitet, versieht das System Schreibvorgänge mit monoton steigenden Sequenznummern, sodass Konfliktbehandlungsregeln stets den aktuellen Versionsstand durchsetzen.

Alle Messungen basieren auf Debug-Builds; detaillierte Auswertungsberichte und Testskripte sind im Projektarchiv hinterlegt.