From 0449f49c234bd5e1e3394ab6b2cf52d9072e2434 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Fri, 20 Jan 2023 23:53:34 +0100 Subject: [PATCH] perf: use improved comparison algorithm This change reduces the time for this rule on the eslint repo down from 453ms to 46ms (= roughly 10x faster). --- lib/rules/no-identical-tests.js | 48 ++++++++++----------------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/lib/rules/no-identical-tests.js b/lib/rules/no-identical-tests.js index e518c268..d8679c5a 100644 --- a/lib/rules/no-identical-tests.js +++ b/lib/rules/no-identical-tests.js @@ -38,48 +38,28 @@ module.exports = { // Helpers // ---------------------------------------------------------------------- /** - *compare two test cases despite of properties order. - *@returns {boolean} if eq, return true, else return false. + * Create a unique cache key + * @param {object} test + * @returns {string} */ - function eq(testA, testB) { - if (testA.type !== testB.type) { - return false; + function toKey(test) { + if (test.type !== 'ObjectExpression') { + return JSON.stringify([test.type, sourceCode.getText(test)]); } - - if (testA.type !== 'ObjectExpression') { - return sourceCode.getText(testA) === sourceCode.getText(testB); - } - - const propertiesA = testA.properties; - const propertiesB = testB.properties; - - // if properties length not eq; return false; - if (propertiesA.length !== propertiesB.length) { - return false; - } - - const propertiesSetA = new Set(); - propertiesA.forEach((item) => { - const code = sourceCode.getText(item); - propertiesSetA.add(code); - }); - - for (const element of propertiesB) { - const code = sourceCode.getText(element); - if (!propertiesSetA.has(code)) { - return false; - } - } - return true; + return JSON.stringify([ + test.type, + ...test.properties.map((p) => sourceCode.getText(p)).sort(), + ]); } return { Program(ast) { utils.getTestInfo(context, ast).forEach((testRun) => { [testRun.valid, testRun.invalid].forEach((tests) => { - const cache = []; + const cache = new Set(); tests.forEach((test) => { - if (cache.some((item) => eq(item, test))) { + const key = toKey(test); + if (cache.has(key)) { context.report({ node: test, messageId: 'identical', @@ -96,7 +76,7 @@ module.exports = { }, }); } else { - cache.push(test); + cache.add(key); } }); });