v0.1.1: perf timings + single-save tag writes + coalesced browser rebuild
Diagnosing the Ctrl+I save hang on the Debian machine (GUI thread blocks past mutter's 5s check-alive): - lintunes/perf.py: timed() context manager logging wall-clock ms at INFO on lintunes.perf — instruments tag/artwork saves, file moves, edit_track(s)_fields, the browser rebuild, smart recompute, and the debounced JSON flush, so the slow machine can tell us which stage eats the time (journalctl --user or a terminal run). - tagging.write_tags: ONE parse + ONE save per edit. grouping/ compilation/bpm ride the main save via registered Easy keys (GRP1/TCMP/TBPM on EasyID3, cpil on EasyMP4) instead of _write_extra_tags re-parsing and re-saving the audio file. - LibraryView: browser rebuilds coalesce through a 0ms single-shot timer — an N-track Get Info edit rebuilds the genre/artist/album cascade once instead of N times over the whole library. Moving the writes off the GUI thread is deliberately deferred until the Debian timings say which stage dominates.
This commit is contained in:
@@ -8,6 +8,7 @@ from PyQt6.QtCore import Qt, QTimer, pyqtSignal
|
||||
|
||||
from lintunes.gui.table_settings import TableSettingsMixin
|
||||
from lintunes.gui.track_table import TrackTableView
|
||||
from lintunes.perf import timed
|
||||
|
||||
|
||||
_ARTICLE_RE = re.compile(r"^the\s+", re.IGNORECASE)
|
||||
@@ -162,6 +163,13 @@ class LibraryView(TableSettingsMixin, QWidget):
|
||||
|
||||
manager.track_updated.connect(self.table.model_.refresh_track)
|
||||
manager.track_fields_edited.connect(self._on_track_fields_edited)
|
||||
# Coalesces browser rebuilds: a multi-track edit emits
|
||||
# track_fields_edited once per track, and rebuilding the whole
|
||||
# genre/artist/album cascade per signal is O(edited × library).
|
||||
self._browser_rebuild_timer = QTimer(self)
|
||||
self._browser_rebuild_timer.setSingleShot(True)
|
||||
self._browser_rebuild_timer.setInterval(0)
|
||||
self._browser_rebuild_timer.timeout.connect(self._rebuild_browser)
|
||||
|
||||
self.reload()
|
||||
|
||||
@@ -295,8 +303,17 @@ class LibraryView(TableSettingsMixin, QWidget):
|
||||
rebuild the lists and re-filter so the renamed value sorts to its new
|
||||
spot and clicking it still finds its tracks (the plain row repaint from
|
||||
track_updated leaves the browser stale). Non-browser edits (name, bpm…)
|
||||
are handled by the proxy's live re-sort, so they need nothing here."""
|
||||
are handled by the proxy's live re-sort, so they need nothing here.
|
||||
|
||||
The rebuild is deferred to a 0 ms single-shot timer so an N-track edit
|
||||
(which fires this once per track) rebuilds the browser once, not N
|
||||
times."""
|
||||
if _BROWSER_FIELDS.intersection(changed_fields):
|
||||
self._browser_rebuild_timer.start()
|
||||
|
||||
def _rebuild_browser(self):
|
||||
with timed("library browser rebuild (%d tracks)",
|
||||
len(self._all_tracks)):
|
||||
self._populate_genres()
|
||||
self._populate_artists()
|
||||
self._populate_albums()
|
||||
|
||||
Reference in New Issue
Block a user