Skip to content

Commit

Permalink
Chore: improve performance of SourceCode constructor (#8054)
Browse files Browse the repository at this point in the history
When generating a list of tokens and comments, the `SourceCode` constructor previously concatenated the list of tokens and the list of comments, and sorted the result. For a file with `n` tokens and `n` comments, this takes `O(nlog(n))` time. However, since the token and comment lists are already sorted, they can be merged in `O(n)` time.

The performance impact of this change is most noticable on large files, since they have a large number of tokens. When linting [test-data.js](https://gist.github.com/mysticatea/2fca6bc8c2194f75e4808a884a1e351a) (48000 lines) with no rules enabled, this improved overall performance by about 20%.
  • Loading branch information
not-an-aardvark committed Feb 11, 2017
1 parent 90fd555 commit b04fde7
Showing 1 changed file with 23 additions and 3 deletions.
26 changes: 23 additions & 3 deletions lib/util/source-code.js
Expand Up @@ -77,6 +77,28 @@ function looksLikeExport(astNode) {
astNode.type === "ExportAllDeclaration" || astNode.type === "ExportSpecifier";
}

/**
* Merges two sorted lists into a larger sorted list in O(n) time
* @param {Token[]} tokens The list of tokens
* @param {Token[]} comments The list of comments
* @returns {Token[]} A sorted list of tokens and comments
*/
function sortedMerge(tokens, comments) {
const result = [];
let tokenIndex = 0;
let commentIndex = 0;

while (tokenIndex < tokens.length || commentIndex < comments.length) {
if (commentIndex >= comments.length || tokenIndex < tokens.length && tokens[tokenIndex].range[0] < comments[commentIndex].range[0]) {
result.push(tokens[tokenIndex++]);
} else {
result.push(comments[commentIndex++]);
}
}

return result;
}


//------------------------------------------------------------------------------
// Public Interface
Expand Down Expand Up @@ -117,9 +139,7 @@ function SourceCode(text, ast) {
*/
this.lines = SourceCode.splitLines(this.text);

this.tokensAndComments = ast.tokens
.concat(ast.comments)
.sort((left, right) => left.range[0] - right.range[0]);
this.tokensAndComments = sortedMerge(ast.tokens, ast.comments);

// create token store methods
const tokenStore = new TokenStore(ast.tokens, ast.comments);
Expand Down

0 comments on commit b04fde7

Please sign in to comment.