perf(renderer): use live HTMLCollection in selection-class toggles
applyQueueSelectionClasses + applyRecentSelectionClasses ran
tbody.querySelectorAll('.queue-row') / ('.recent-file-row') on every
click. querySelectorAll always walks the tree and returns a fresh
static NodeList. With 200 visible queue rows + frequent click/drag
selections that's a measurable per-click cost.
Switch to getElementsByClassName: returns a live HTMLCollection that
the engine memoizes and updates incrementally as nodes are
inserted/removed. First call still walks once; subsequent calls are
near-free reads. Iteration uses a plain index loop because
HTMLCollection is array-like, not iterable in older runtimes (it is
in modern Chromium, but the index loop is also marginally faster).
No behaviour change. 87/87 still green.
This commit is contained in:
parent
0df8557f06
commit
678c9ce3c5
@ -900,11 +900,17 @@ function scheduleRecentRender() {
|
|||||||
|
|
||||||
// Toggle the .selected class on existing rows without rebuilding the table.
|
// Toggle the .selected class on existing rows without rebuilding the table.
|
||||||
// Used on click/selection changes — O(rendered rows) instead of O(total rows × sort).
|
// Used on click/selection changes — O(rendered rows) instead of O(total rows × sort).
|
||||||
|
// Uses getElementsByClassName for the live HTMLCollection (DOM-cached after the
|
||||||
|
// first call, auto-tracks insertions/removals on tbody) instead of running a
|
||||||
|
// fresh querySelectorAll on every click. At 200 visible rows that's the
|
||||||
|
// difference between paying for a tree walk per click vs reading a memoized
|
||||||
|
// list that the engine already maintains.
|
||||||
function applyQueueSelectionClasses() {
|
function applyQueueSelectionClasses() {
|
||||||
const tbody = document.getElementById('queueBody');
|
const tbody = document.getElementById('queueBody');
|
||||||
if (!tbody) return;
|
if (!tbody) return;
|
||||||
const rows = tbody.querySelectorAll('.queue-row');
|
const rows = tbody.getElementsByClassName('queue-row');
|
||||||
for (const tr of rows) {
|
for (let i = 0; i < rows.length; i++) {
|
||||||
|
const tr = rows[i];
|
||||||
tr.classList.toggle('selected', selectedJobIds.has(tr.dataset.jobId));
|
tr.classList.toggle('selected', selectedJobIds.has(tr.dataset.jobId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -912,8 +918,9 @@ function applyQueueSelectionClasses() {
|
|||||||
function applyRecentSelectionClasses() {
|
function applyRecentSelectionClasses() {
|
||||||
const tbody = document.getElementById('recentFilesBody');
|
const tbody = document.getElementById('recentFilesBody');
|
||||||
if (!tbody) return;
|
if (!tbody) return;
|
||||||
const rows = tbody.querySelectorAll('.recent-file-row');
|
const rows = tbody.getElementsByClassName('recent-file-row');
|
||||||
for (const tr of rows) {
|
for (let i = 0; i < rows.length; i++) {
|
||||||
|
const tr = rows[i];
|
||||||
const order = parseInt(tr.dataset.order, 10);
|
const order = parseInt(tr.dataset.order, 10);
|
||||||
tr.classList.toggle('selected', selectedRecentIds.has(order));
|
tr.classList.toggle('selected', selectedRecentIds.has(order));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,12 +5,10 @@
|
|||||||
- ✅ 3.3.1 — `removeFromQueueOnDone` coalesced via microtask (kein O(N²) mehr bei done-Bursts)
|
- ✅ 3.3.1 — `removeFromQueueOnDone` coalesced via microtask (kein O(N²) mehr bei done-Bursts)
|
||||||
- ✅ 3.3.2 — `fileuploader.log` Auto-Rotation bei 50 MB (max 3 Backups: .1 .2 .3)
|
- ✅ 3.3.2 — `fileuploader.log` Auto-Rotation bei 50 MB (max 3 Backups: .1 .2 .3)
|
||||||
- ✅ 3.3.3 — `_jobLogCollector` Cap auf 1000 tracked jobs (FIFO-eviction beim Überschreiten)
|
- ✅ 3.3.3 — `_jobLogCollector` Cap auf 1000 tracked jobs (FIFO-eviction beim Überschreiten)
|
||||||
|
- ✅ 3.3.4 — `applyQueueSelectionClasses` + `applyRecentSelectionClasses` nutzen `getElementsByClassName` (live HTMLCollection statt querySelectorAll re-query bei jedem Klick)
|
||||||
|
|
||||||
## Open items (priorisiert)
|
## Open items (priorisiert)
|
||||||
|
|
||||||
### Performance
|
|
||||||
- [ ] **`applyQueueSelectionClasses`** (renderer/app.js:891) — `tbody.querySelectorAll` bei jedem Klick. Bei 5000-Jobs-Queue O(N) per click. Cache last rendered range.
|
|
||||||
|
|
||||||
### Code-Qualität
|
### Code-Qualität
|
||||||
- [ ] **Test-Coverage für 3.3.0** — keine Tests für die queue-cap-prune-Logik in handleBatchDone, sortQueueJobs dynamic-throttle, log-error-recovery.
|
- [ ] **Test-Coverage für 3.3.0** — keine Tests für die queue-cap-prune-Logik in handleBatchDone, sortQueueJobs dynamic-throttle, log-error-recovery.
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user