Bug 1739990 - Fix perf regression in getInScopeLines. r=jdescottes.

The patch for Bug 1737993 did a very readable but not performant replacement
of lodash `without` usage in `getInScopeLines`.
This patch changes things a bit so we get a similar level of performance as
what we had before, when using `without`.
For this we :
- make `getOutOfScopeLines` returns a `Set` so checking inclusion is faster
- create the final array of "in scope lines" using a for loop and assigning
  line number when needed, and then filtering out empty slots.

Differential Revision: https://phabricator.services.mozilla.com/D130742
This commit is contained in:
Nicolas Chevobbe 2021-11-09 14:37:43 +00:00
Родитель 4ad52902c3
Коммит 3b6ea985b0
1 изменённых файлов: 26 добавлений и 10 удалений

Просмотреть файл

@ -10,7 +10,6 @@ import {
import { getSourceLineCount } from "../../utils/source";
import { range, flatMap, uniq } from "lodash";
import { isFulfilled } from "../../utils/async-value";
function getOutOfScopeLines(outOfScopeLocations) {
@ -18,11 +17,14 @@ function getOutOfScopeLines(outOfScopeLocations) {
return null;
}
return uniq(
flatMap(outOfScopeLocations, location =>
range(location.start.line, location.end.line)
)
);
const uniqueLines = new Set();
for (const location of outOfScopeLocations) {
for (let i = location.start.line; i < location.end.line; i++) {
uniqueLines.add(i);
}
}
return uniqueLines;
}
async function getInScopeLines(cx, location, { dispatch, getState, parser }) {
@ -39,11 +41,25 @@ async function getInScopeLines(cx, location, { dispatch, getState, parser }) {
? 0
: getSourceLineCount(source.content.value);
const sourceLines = range(1, sourceNumLines + 1);
const noLinesOutOfScope =
linesOutOfScope == null || linesOutOfScope.size == 0;
return !linesOutOfScope
? sourceLines
: sourceLines.filter(sourceLine => !linesOutOfScope.includes(sourceLine));
// This operation can be very costly for large files so we sacrifice a bit of readability
// for performance sake.
// We initialize an array with a fixed size and we'll directly assign value for lines
// that are not out of scope. This is much faster than having an empty array and pushing
// into it.
const sourceLines = new Array(sourceNumLines);
for (let i = 0; i < sourceNumLines; i++) {
const line = i + 1;
if (noLinesOutOfScope || !linesOutOfScope.has(line)) {
sourceLines[i] = line;
}
}
// Finally we need to remove any undefined values, i.e. the ones that were matching
// out of scope lines.
return sourceLines.filter(i => i != undefined);
}
export function setInScopeLines(cx) {