From 23cb30fc0c5636f63c3028669b4959c044080730 Mon Sep 17 00:00:00 2001 From: Oliver Giles Date: Sat, 22 Jan 2022 20:07:23 +1300 Subject: [PATCH] fe perf: throttle log rendering as a further enhancement to efafda16f, schedule a render immediately if 500ms have passed without one, and cap the max delay to 500ms. This removes delay for short logs, and prevents an issue where output that is produced reasonably quickly will not be rendered for a long time. --- src/resources/js/app.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/resources/js/app.js b/src/resources/js/app.js index 5211dc6..124b81b 100644 --- a/src/resources/js/app.js +++ b/src/resources/js/app.js @@ -655,6 +655,7 @@ const Run = templateId => { let logToRender = ''; let logComplete = false; let tid = null; + let lastUiUpdate = 0; function updateUI() { // output may contain private ANSI CSI escape sequence to point to @@ -679,6 +680,9 @@ const Run = templateId => { // output finished state.logComplete = true; } + + lastUiUpdate = Date.now(); + tid = null; } return function pump() { @@ -687,16 +691,22 @@ const Run = templateId => { // do not set state.logComplete directly, because rendering // may take some time, and we don't want the progress indicator // to disappear before rendering is complete. Instead, delay - // it until after the log has been added to the DOM + // it until after the entire log has been rendered logComplete = true; + // if no render update is pending, schedule one immediately + // (do not use the delayed buffering mechanism from below), so + // that for the common case of short logs, the loading spinner + // disappears immediately as the log is rendered + if(tid === null) + setTimeout(updateUI, 0); return; } - logToRender += utf8decoder.decode(value); // sometimes logs can be very large, and we are calling pump() // furiously to get all the data to the client. To prevent straining // the client renderer, buffer the data and delay the UI updates. - clearTimeout(tid); - tid = setTimeout(updateUI, 125); + logToRender += utf8decoder.decode(value); + if(tid === null) + tid = setTimeout(updateUI, Math.max(500 - (Date.now() - lastUiUpdate), 0)); return pump(); }); }();