Refactor lintInput to share code between sync/async, support an async path for strings, and process files first for better concurrency.

This commit is contained in:
David Anson 2021-12-03 22:43:58 -08:00
parent 53e5e4272e
commit e531bd6359
2 changed files with 101 additions and 119 deletions

View file

@ -1608,65 +1608,63 @@ function lintInput(options, synchronous, callback) {
var fs = options.fs || __webpack_require__(/*! fs */ "?ec0a");
var results = newResults(ruleList);
var done = false;
// Linting of strings is always synchronous
var syncItem = null;
// eslint-disable-next-line jsdoc/require-jsdoc
function syncCallback(err, result) {
if (err) {
done = true;
return callback(err);
}
results[syncItem] = result;
return null;
}
while (!done && (syncItem = stringsKeys.shift())) {
lintContent(ruleList, syncItem, strings[syncItem] || "", md, config, frontMatter, handleRuleFailures, noInlineConfig, resultVersion, syncCallback);
}
if (synchronous) {
// Lint files synchronously
while (!done && (syncItem = files.shift())) {
lintFile(ruleList, syncItem, md, config, frontMatter, handleRuleFailures, noInlineConfig, resultVersion, fs, synchronous, syncCallback);
}
return done || callback(null, results);
}
// Lint files asynchronously
var concurrency = 0;
// eslint-disable-next-line jsdoc/require-jsdoc
function lintConcurrently() {
var asyncItem = files.shift();
if (done) {
// Nothing to do
}
else if (asyncItem) {
concurrency++;
lintFile(ruleList, asyncItem, md, config, frontMatter, handleRuleFailures, noInlineConfig, resultVersion, fs, synchronous, function (err, result) {
function lintWorker() {
var currentItem = null;
// eslint-disable-next-line jsdoc/require-jsdoc
function lintWorkerCallback(err, result) {
concurrency--;
if (err) {
done = true;
return callback(err);
}
results[asyncItem] = result;
lintConcurrently();
results[currentItem] = result;
if (!synchronous) {
lintWorker();
}
return null;
});
}
if (done) {
// Abort for error or nothing left to do
}
else if (files.length > 0) {
// Lint next file
concurrency++;
currentItem = files.shift();
lintFile(ruleList, currentItem, md, config, frontMatter, handleRuleFailures, noInlineConfig, resultVersion, fs, synchronous, lintWorkerCallback);
}
else if (stringsKeys.length > 0) {
// Lint next string
concurrency++;
currentItem = stringsKeys.shift();
lintContent(ruleList, currentItem, strings[currentItem] || "", md, config, frontMatter, handleRuleFailures, noInlineConfig, resultVersion, lintWorkerCallback);
}
else if (concurrency === 0) {
// Finish
done = true;
return callback(null, results);
}
return null;
}
if (synchronous) {
while (!done) {
lintWorker();
}
}
else {
// Testing on a Raspberry Pi 4 Model B with an artificial 5ms file access
// delay suggests that a concurrency factor of 8 can eliminate the impact
// of that delay (i.e., total time is the same as with no delay).
lintConcurrently();
lintConcurrently();
lintConcurrently();
lintConcurrently();
lintConcurrently();
lintConcurrently();
lintConcurrently();
lintConcurrently();
lintWorker();
lintWorker();
lintWorker();
lintWorker();
lintWorker();
lintWorker();
lintWorker();
lintWorker();
}
return null;
}
/**

View file

@ -749,98 +749,82 @@ function lintInput(options, synchronous, callback) {
const fs = options.fs || require("fs");
const results = newResults(ruleList);
let done = false;
// Linting of strings is always synchronous
let syncItem = null;
// eslint-disable-next-line jsdoc/require-jsdoc
function syncCallback(err, result) {
if (err) {
done = true;
return callback(err);
}
results[syncItem] = result;
return null;
}
while (!done && (syncItem = stringsKeys.shift())) {
lintContent(
ruleList,
syncItem,
strings[syncItem] || "",
md,
config,
frontMatter,
handleRuleFailures,
noInlineConfig,
resultVersion,
syncCallback
);
}
if (synchronous) {
// Lint files synchronously
while (!done && (syncItem = files.shift())) {
lintFile(
ruleList,
syncItem,
md,
config,
frontMatter,
handleRuleFailures,
noInlineConfig,
resultVersion,
fs,
synchronous,
syncCallback
);
}
return done || callback(null, results);
}
// Lint files asynchronously
let concurrency = 0;
// eslint-disable-next-line jsdoc/require-jsdoc
function lintConcurrently() {
const asyncItem = files.shift();
if (done) {
// Nothing to do
} else if (asyncItem) {
concurrency++;
lintFile(
ruleList,
asyncItem,
md,
config,
frontMatter,
handleRuleFailures,
noInlineConfig,
resultVersion,
fs,
synchronous,
(err, result) => {
function lintWorker() {
let currentItem = null;
// eslint-disable-next-line jsdoc/require-jsdoc
function lintWorkerCallback(err, result) {
concurrency--;
if (err) {
done = true;
return callback(err);
}
results[asyncItem] = result;
lintConcurrently();
results[currentItem] = result;
if (!synchronous) {
lintWorker();
}
return null;
}
if (done) {
// Abort for error or nothing left to do
} else if (files.length > 0) {
// Lint next file
concurrency++;
currentItem = files.shift();
lintFile(
ruleList,
currentItem,
md,
config,
frontMatter,
handleRuleFailures,
noInlineConfig,
resultVersion,
fs,
synchronous,
lintWorkerCallback
);
} else if (stringsKeys.length > 0) {
// Lint next string
concurrency++;
currentItem = stringsKeys.shift();
lintContent(
ruleList,
currentItem,
strings[currentItem] || "",
md,
config,
frontMatter,
handleRuleFailures,
noInlineConfig,
resultVersion,
lintWorkerCallback
);
} else if (concurrency === 0) {
// Finish
done = true;
return callback(null, results);
}
return null;
}
if (synchronous) {
while (!done) {
lintWorker();
}
} else {
// Testing on a Raspberry Pi 4 Model B with an artificial 5ms file access
// delay suggests that a concurrency factor of 8 can eliminate the impact
// of that delay (i.e., total time is the same as with no delay).
lintConcurrently();
lintConcurrently();
lintConcurrently();
lintConcurrently();
lintConcurrently();
lintConcurrently();
lintConcurrently();
lintConcurrently();
lintWorker();
lintWorker();
lintWorker();
lintWorker();
lintWorker();
lintWorker();
lintWorker();
lintWorker();
}
return null;
}