v0.7.0: startup speed — the 21k-track library stops freezing
Three reported symptoms, one shape: every operation was whole-library, whole-file, on the Qt main thread. Measured on the real library (21,482 tracks, 506 playlists, 15 MB library.json). The track table sorted through a QSortFilterProxyModel, which asks data() for a value on every comparison — 580k Python round trips, 8.5 s per table load, paid again on every reload. TrackTableModel now keeps _tracks in canonical (playlist) order plus an _order index list and sorts a key list computed once per track. Nothing used the proxy's filtering. Sorting by # is the identity order, so "source row" still means "playlist position" for drag-reorder. 8.5 s -> 0.13 s; MainWindow() 18.1 s -> 0.79 s. Smart rules compile to closures once per evaluate() instead of being re-dispatched per track — the operator lookup, casefolding the query and parsing the rule's own date constants all leave the 21k-iteration loop (_match_date was re-parsing its own constant 21,482 times per rule). Verified identical membership against the old evaluator on all 20 real smart playlists. 2.54 s -> 0.72 s, and it now runs after the first paint. Also: _reconcile_track skips two to_dict() round trips per unchanged track (MERGEABLE_FIELDS in the resolver is the single source of truth for what a merge touches); no git subprocess on the startup path (Updater.enabled is probed lazily on the background thread, version-button tooltip deferred); and .resolved/ is pruned to the newest 10 snapshots — it had reached 1.7 GB across 73 snapshots inside the Syncthing share. Time to interactive window ~15 s -> 3.2 s. The mid-session freeze when Syncthing delivers a change — a full reload + recompute + table rebuild with the window already on screen, which is what GNOME was offering to force-quit — ~16 s -> 3.8 s. The merge rework itself (playlist ordering, per-machine play journal, quieting the dialog) is queued in TASKS.md as Round 36. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -330,7 +330,7 @@ class TestRatingClicks:
|
||||
emitted = []
|
||||
view.rating_edited.connect(lambda tid, r: emitted.append((tid, r)))
|
||||
col = view.model_.fields.index("rating")
|
||||
rect = view.visualRect(view.proxy.index(0, col))
|
||||
rect = view.visualRect(view.model_.index(0, col))
|
||||
slot_w = rating_slot_width(QFontMetrics(view.font()))
|
||||
# Click the 4th slot → 80.
|
||||
x = rect.left() + RATING_LEFT_PAD + int(slot_w * 3.5)
|
||||
@@ -356,10 +356,10 @@ class TestRatingClicks:
|
||||
track = Track(track_id=1, name="A", rating=40)
|
||||
view = self._view(qapp, [track])
|
||||
col = view.model_.fields.index("rating")
|
||||
index = view.proxy.index(0, col)
|
||||
index = view.model_.index(0, col)
|
||||
view._set_rating_hover(index)
|
||||
assert view.is_rating_hovered(index)
|
||||
assert not view.is_rating_hovered(view.proxy.index(0, 0))
|
||||
assert not view.is_rating_hovered(view.model_.index(0, 0))
|
||||
view._set_rating_hover(None)
|
||||
assert not view.is_rating_hovered(index)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user