Skip to content

Commit

Permalink
🐎 Epic performance boost for large files
Browse files Browse the repository at this point in the history
Spectacularly improve rendering performance by only redrawing the
minimap at specific intervals instead of on each keystroke.
  • Loading branch information
robertrossmann committed Mar 23, 2017
1 parent 9f652d7 commit 07e65ed
Showing 1 changed file with 51 additions and 2 deletions.
53 changes: 51 additions & 2 deletions lib/minimap.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ class Minimap {
* @access private
*/
this.configDevicePixelRatioRounding = null
/**
/**
* A boolean value to store whether this Minimap have been destroyed or not.
*
Expand All @@ -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) {
Expand Down Expand Up @@ -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() }))

Expand All @@ -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
Expand All @@ -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.
*
Expand Down

0 comments on commit 07e65ed

Please sign in to comment.