perf(renderer): coalesce status-change UI updates into one rAF frame
Non-uploading progress events (queued/getting-server/retrying/done/ error/aborted/skipped) were firing renderQueueTable + updateQueueActionButtons + updateStatusBar + updateStatsPanel synchronously on EVERY event. At batch start, 500 jobs going preview→queued→getting-server within milliseconds meant ~2000 sync DOM updates — visible jank on large batches. New scheduleStatusChangeUpdate() uses requestAnimationFrame to coalesce the four-helper call into at most one run per frame (~60 Hz). Functional result is identical; the user just sees smooth flips instead of a briefly frozen renderer. The uploading-progress throttle (200ms) is unchanged since those events are much more frequent and the user doesn't need 60 Hz upload-byte updates.
This commit is contained in:
parent
4bf159eda2
commit
058c8a2674
@ -918,6 +918,23 @@ function scheduleThrottledUIUpdate() {
|
|||||||
}, UI_UPDATE_INTERVAL);
|
}, UI_UPDATE_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Coalesces status-change updates (done/error/retrying/queued/…) into one
|
||||||
|
// frame. Without this, a batch of 500 jobs flipping queued→getting-server
|
||||||
|
// →uploading synchronously fires 1500+ updateStatusBar/Buttons/Stats calls
|
||||||
|
// and janks the renderer. rAF caps it to ~60 Hz.
|
||||||
|
let _statusChangeUpdateQueued = false;
|
||||||
|
function scheduleStatusChangeUpdate() {
|
||||||
|
if (_statusChangeUpdateQueued) return;
|
||||||
|
_statusChangeUpdateQueued = true;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
_statusChangeUpdateQueued = false;
|
||||||
|
renderQueueTable();
|
||||||
|
updateQueueActionButtons();
|
||||||
|
updateStatusBar();
|
||||||
|
updateStatsPanel();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function buildRowHtml(job) {
|
function buildRowHtml(job) {
|
||||||
const statusClass = `status-${job.status}`;
|
const statusClass = `status-${job.status}`;
|
||||||
const rowClass = `queue-row ${statusClass}${selectedJobIds.has(job.id) ? ' selected' : ''}`;
|
const rowClass = `queue-row ${statusClass}${selectedJobIds.has(job.id) ? ' selected' : ''}`;
|
||||||
@ -1859,14 +1876,13 @@ function handleProgress(data) {
|
|||||||
queueJobs = queueJobs.filter(j => j !== job);
|
queueJobs = queueJobs.filter(j => j !== job);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status changes (done/error/etc) get immediate render; ongoing progress is throttled
|
// Status changes (done/error/etc) get one coalesced update per frame so a
|
||||||
|
// burst of 500 parallel jobs flipping state doesn't fire 2000 sync DOM
|
||||||
|
// updates. Ongoing uploading progress is throttled at 200ms.
|
||||||
if (data.status === 'uploading') {
|
if (data.status === 'uploading') {
|
||||||
scheduleThrottledUIUpdate();
|
scheduleThrottledUIUpdate();
|
||||||
} else {
|
} else {
|
||||||
scheduleQueueRender();
|
scheduleStatusChangeUpdate();
|
||||||
updateQueueActionButtons();
|
|
||||||
updateStatusBar();
|
|
||||||
updateStatsPanel();
|
|
||||||
}
|
}
|
||||||
persistQueueStateSoon();
|
persistQueueStateSoon();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user