From af29effbf3f743eb35c15980c25192cb4e59ba27 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 13 Jun 2016 12:37:16 -0700 Subject: [PATCH] Allow refresh to execute 30 times a second maximum For commands that pass a significant amount of output to the write function, this prevents the terminal maxing out the CPU and making the UI unresponsive. While commands can still run beyond what they do on the terminal, it is far better with a debounce in place as every single terminal manipulation does not need to be constructed in the DOM. A side-effect of this is that it makes ^C to interrupt a process seem more responsive. Fixes #127 Fixes #126 --- src/xterm.js | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/xterm.js b/src/xterm.js index 3d29a66f..5a275b8b 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -230,6 +230,16 @@ */ this.y = 0; + /** + * Used to debounce the refresh function + */ + this.isRefreshing = false; + + /** + * Whether there is a full terminal refresh queued + */ + this.queuedRefresh = false; + this.cursorState = 0; this.cursorHidden = false; this.convertEol; @@ -297,6 +307,7 @@ this.tabs; this.setupStops(); + this.debounceRefresh(); } inherits(Terminal, EventEmitter); @@ -307,6 +318,26 @@ return (this.defAttr & ~0x1ff) | (this.curAttr & 0x1ff); }; + /** + * Allow refresh to execute only approximately 30 times a second. For commands that pass a + * significant amount of output to the write function, this prevents the terminal from maxing + * out the CPU and making the UI unresponsive. While commands can still run beyond what they do + * on the terminal, it is far better with a debounce in place as every single terminal + * manipulation does not need to be constructed in the DOM. + * + * A side-effect of this is that it makes ^C to interrupt a process seem more responsive. + */ + Terminal.prototype.debounceRefresh = function () { + var self = this; + window.setInterval(function () { + self.isRefreshing = false; + if (self.queuedRefresh) { + // Do a full refresh in case multiple refreshes were requested. + self.refresh(0, self.rows - 1); + } + }, 34); + }; + /** * Colors */ @@ -1151,6 +1182,12 @@ Terminal.prototype.refresh = function(start, end) { var x, y, i, line, out, ch, width, data, attr, bg, fg, flags, row, parent, focused = document.activeElement; + if (this.isRefreshing) { + this.queuedRefresh = true; + return; + } + this.isRefreshing = true; + if (end - start >= this.rows / 2) { parent = this.element.parentNode; if (parent) parent.removeChild(this.element);