From 07e65ed88d31a36d49749cc1b02c1fef993faa28 Mon Sep 17 00:00:00 2001 From: Robert Rossmann Date: Thu, 23 Mar 2017 13:10:07 +0100 Subject: [PATCH] :racehorse: Epic performance boost for large files Spectacularly improve rendering performance by only redrawing the minimap at specific intervals instead of on each keystroke. --- lib/minimap.js | 53 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/lib/minimap.js b/lib/minimap.js index 0d887257..0a390343 100644 --- a/lib/minimap.js +++ b/lib/minimap.js @@ -162,7 +162,6 @@ class Minimap { * @access private */ this.configDevicePixelRatioRounding = null - /** /** * A boolean value to store whether this Minimap have been destroyed or not. * @@ -179,6 +178,23 @@ class Minimap { */ this.scrollPastEnd = false + /** + * An array of changes registered with textEditor.onDidChange() which have not yet been handled + * + * @type {Array} + * @access private + */ + this.pendingChangeEvents = [] + + /** + * Timer reference which, once fired, will flush all the pending changes stored in + * this.pendingChangeEvents array. + * + * @type {Timer?} + * @access private + */ + this.flushChangesTimer = null + this.initializeDecorations() if (atom.views.getView(this.textEditor).getScrollTop != null) { @@ -234,7 +250,7 @@ class Minimap { })) subs.add(this.textEditor.onDidChange((changes) => { - this.emitChanges(changes) + this.scheduleChanges(changes) })) subs.add(this.textEditor.onDidDestroy(() => { this.destroy() })) @@ -260,6 +276,9 @@ class Minimap { destroy () { if (this.destroyed) { return } + clearTimeout(this.flushChangesTimer) + this.flushChangesTimer = null + this.pendingChangeEvents = [] this.removeAllDecorations() this.subscriptions.dispose() this.subscriptions = null @@ -276,6 +295,36 @@ class Minimap { */ isDestroyed () { return this.destroyed } + /** + * Schedule changes from textEditor.onDidChange() to be handled at a later time + * + * @param {Array} changes The changes to be scheduled + * @return void + * @access private + */ + scheduleChanges (changes) { + this.pendingChangeEvents.push(...changes) + + // If any changes happened within the timeout's delay, a timeout will already have been + // scheduled -> no need to schedule again + if (!this.flushChangesTimer) { + this.flushChangesTimer = setTimeout(() => { this.flushChanges() }, 1000) + } + } + + /** + * Flush all changes which have been scheduled for later processing by this.scheduleChanges() + * + * @return void + * @access private + */ + flushChanges () { + clearTimeout(this.flushChangesTimer) + this.flushChangesTimer = null + this.emitChanges(this.pendingChangeEvents) + this.pendingChangeEvents = [] + } + /** * Registers an event listener to the `did-change` event. *