Cuando una biblioteca musical alcanza cientos de miles de pistas, el desplazamiento en pantalla inicial suele ser fluido, pero la paginación profunda, el salto por iniciales y la búsqueda global acumulan una latencia considerable. Mediante un conjunto de datos de prueba con 500.500 canciones, medimos los tiempos de ejecución de las principales rutas de lectura e implementamos un mecanismo de espejo de solo lectura local previsto para la versión 7.0.
Nota de versión: la versión 6.0 ya incluyó optimizaciones de rendimiento básicas. El espejo de lectura de alto rendimiento descrito en este artículo está proyectado para la versión 7.0 y se encuentra en pruebas internas. Todas las cifras proceden de compilaciones de desarrollo internas.
La arquitectura genera localmente una copia derivada de solo lectura de la biblioteca en formato SQLite. Durante la fase de indexación, se calculan con antelación las claves de ordenación, los criterios de filtrado y las anclas de índice A-Z, almacenándolos en disco. El almacenamiento nativo del sistema conserva la autoridad sobre los datos originales, mientras que el espejo de solo lectura atiende las consultas frecuentes y permite operaciones independientes de reconstrucción o limpieza.
Resultados de rendimiento medidos
Las mediciones se realizaron en un Mac mini M4 con el conjunto de 500.500 canciones, superando pruebas de coherencia campo por campo:
| Ruta de lectura | Escala | Almacenamiento nativo | Espejo | Aceleración |
|---|---|---|---|---|
| Creación de instantánea de lista | 10k | 3030 ms | 21 ms | ~143× |
| Paginación de lista (con filtros) | 10k | 1984 ms | 8,2 ms | ~242× |
| Salto de ancla A-Z | 10k | ~2050 ms | 0,4–7,6 ms | 274–5100× |
| Página profunda (offset 450k) | 500k | ~28 min/página | ~0,9 s | ~1800× |
| Comprobación sin resultados «filas visibles» | 100k | 98,1 s | 46 ms | ~2100× |
| Candidatos multicriterio para listas inteligentes | 100k | 6,9 s | 1,27 s | ~5,4× |
| Vista de lista / detalle de artista / carga inicial | 50k | – | – | 4,5–7,3× |
Con 500.000 pistas, la ruta nativa depende de un escaneo secuencial de la tabla completa, lo que incrementa el tiempo de ejecución con la profundidad del desplazamiento: obtener una página cerca de la pista 400.000 requería unos 1668 segundos como referencia. El espejo de solo lectura reduce este tiempo a un intervalo de entre 0,8 y 1,4 segundos, manteniendo una respuesta estable sin importar la profundidad de consulta.
Etiquetas de ordenación y compatibilidad de vistas
En géneros como música clásica o jazz, suele emplearse la opción de etiquetas de ordenación (Sort Tags) para clasificar a «The Beatles» bajo la letra B («Beatles, The»). El espejo almacena dos juegos independientes de claves de ordenación para los cinco campos compatibles. Al alternar estas etiquetas, la consulta selecciona directamente la columna correspondiente sin exigir la regeneración del índice, y la barra A-Z se adapta de forma inmediata.
Las vistas agregadas de álbumes, artistas y compositores también aprovechan las consultas aceleradas del espejo. No obstante, si se activan las etiquetas de ordenación en estas vistas, el sistema conmuta a la ruta de almacenamiento primario para reflejar con precisión los valores de nivel de entidad. La implementación de tablas agregadas en el lado de escritura está contemplada en la planificación futura.
Consumo de recursos y compromisos
El mantenimiento de un espejo de lectura local requiere tiempo de indexación y espacio en el almacenamiento interno:
- Tiempo de generación: la creación completa del índice se ejecuta en segundo plano. Para 500.000 pistas, el proceso inicial dura unos 32 minutos, manteniendo accesible la navegación en modo estándar durante la tarea; para 50.000 pistas, finaliza en unos 35 segundos.
- Espacio en disco: el archivo de espejo para 500.000 pistas requiere cerca de 2,1 GB de almacenamiento. La pantalla de Ajustes desglosa el espacio ocupado; desactivar el modo conserva los datos para una reactivación inmediata y permite también un borrado completo.
- Sobrecarga de escritura: al guardar metadatos de las canciones se actualiza el espejo en sincronía, lo que añade unos 20 ms por confirmación en lote en nuestras pruebas.
Por estas razones, la característica permanece desactivada de forma predeterminada, permitiendo al usuario activarla según las dimensiones de su colección.
Mecanismos principales de optimización
- Proyección de valores ligeros: la ruta habitual instancia grafos completos de objetos gestionados para cada fila; el espejo lee directamente filas de SQLite y proyecta tipos de valor ligeros, minimizando la sobrecarga de gestión de memoria y CPU.
- Descenso de predicados: los filtros, criterios de ordenación y deduplicación se procesan en el propio motor de base de datos, reduciendo el volumen antes de transferir datos a memoria.
- Precalculado de claves de ordenación e índices: las claves normalizadas y las letras de sección A-Z se calculan al persistir los registros. Las consultas combinan paginación por claves (Keyset Pagination) con escaneos de índice, garantizando una velocidad regular en páginas profundas.
Coherencia de datos y detalles de implementación
Para comprobar que los resultados del espejo coinciden plenamente con el almacenamiento principal, las pruebas evaluaron combinaciones de 19 columnas de ordenación, direcciones ascendentes y descendentes, estado de etiquetas y filtros compuestos. Se resolvieron varios casos de borde durante la integración:
- Valores nulos y cadenas vacías: la regla de etiquetas de ordenación prioriza el tag y recurre al nombre para mostrar en su ausencia. Debido a las diferencias de evaluación entre los operadores de Swift y las funciones SQL frente a cadenas vacías, el espejo separa ambas claves en columnas distintas y las selecciona de manera explícita en la consulta.
- Compatibilidad de ordenación en campos históricos: la duración de las pistas se ordenaba históricamente mediante comparación de cadenas de texto (situando «120.0» antes de «90.0»). Para respetar el comportamiento existente, los campos de texto cuentan con claves de ordenación textuales independientes, reservando los índices numéricos para valores estrictamente cuantitativos.
- Definición uniforme de espacios en blanco: como las definiciones de espacio en blanco en Swift y en las funciones de recorte estándar de SQL presentan ligeras variaciones, se incorporaron indicadores de estado en el flujo de escritura para unificar la comprobación de contenido vacío.
- Segmentación en indexaciones extensas: con 500.000 registros, los desencadenadores de búsqueda de texto completo realizan escrituras múltiples de índice, elevando el tiempo total a unos 32 minutos. El flujo está estructurado en bloques independientes con soporte para reanudar el trabajo tras una interrupción.
- Control de escrituras simultáneas: si se editan metadatos durante la reconstrucción del índice, cada escritura incluye un número de secuencia estrictamente creciente, permitiendo a las reglas de resolución de conflictos fijar la versión más reciente con total exactitud.
Los datos presentados corresponden a compilaciones de depuración; los registros de pruebas y las herramientas de verificación están documentados en el repositorio.
