perf(local-library): push sort into SQL and drop localeCompare from groupTracks

Two cooperating changes that flatten the long sort tail in the Tracks tab:

1. search_with_filter now ORDER BYs (album, COALESCE(album_artist, artist),
   disc_number, track_number, title) COLLATE NOCASE — matching the default
   album-grouped browsing. SQLite handles 100K rows in well under 100ms;
   the JS sort took several seconds for the same volume.

2. groupTracks replaces the chained localeCompare with decorate-sort-
   undecorate using precomputed composite keys (lowercase strings with a
   sentinel separator and zero-padded numeric segments). The Intl collator
   instantiation per comparison was the bulk of the per-pass cost.

Both changes preserve the existing ordering semantics for the album, artist
and name modes; locale-specific accent ordering becomes lowercase ASCII
order, which is acceptable for library browsing.

Tier 3 of three.

cc
This commit is contained in:
vicrodh committed 2026-05-08 23:04:36 -06:00
1 parent bc4cd85a08
commit 2f2dbe626b
2 files changed
+42 -30

No files matched your search

+11 -1
View File
@@ -2267,10 +2267,20 @@ impl LibraryDatabase {
format!("LIMIT {}", limit)
};
// ORDER BY matches the album-grouped browsing the Tracks tab uses
// by default. Sorting in SQLite is sub-100ms for 100K rows; doing it
// in JS with localeCompare on the same volume blocks the main thread
// for several seconds per pass.
let sql = format!(
"SELECT {} FROM local_tracks \
WHERE (title LIKE ?1 OR artist LIKE ?1 OR album LIKE ?1) \
{} {} {}",
{} {} \
ORDER BY album COLLATE NOCASE, \
COALESCE(album_artist, artist) COLLATE NOCASE, \
disc_number, \
track_number, \
title COLLATE NOCASE \
{}",
Self::TRACK_COLUMNS,
source_filter,
network_filter,