From 47a3fe4e199d3b03b5f0fb9b9fa4f0d46d98a12f Mon Sep 17 00:00:00 2001 From: Matt <7128721+TobiTenno@users.noreply.github.com> Date: Thu, 19 Dec 2024 09:05:24 -0600 Subject: [PATCH] perf: optimize index.spec.mjs for memory (#673) --- .github/workflows/regression.sh | 2 +- .github/workflows/static.yaml | 2 +- package-lock.json | 17 +++++++++++ package.json | 1 + test/index.spec.mjs | 51 +++++++++++++++++++++++---------- 5 files changed, 56 insertions(+), 17 deletions(-) diff --git a/.github/workflows/regression.sh b/.github/workflows/regression.sh index 6bb62affb..15314edcb 100755 --- a/.github/workflows/regression.sh +++ b/.github/workflows/regression.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash { - NODE_OPTIONS=--max_old_space_size=8192 npm test && exit 0 + NODE_OPTIONS='--max_old_space_size=2048' npm test && exit 0 } || { echo "Regression failed, rolling back..." cd "${GITHUB_WORKSPACE}" && git checkout -- . && exit 0 diff --git a/.github/workflows/static.yaml b/.github/workflows/static.yaml index 13ad91c74..2f8bcb853 100644 --- a/.github/workflows/static.yaml +++ b/.github/workflows/static.yaml @@ -98,7 +98,7 @@ jobs: - run: npm i --no-save warframe-worldstate-data@^2 - name: Test env: - NODE_OPTIONS: '--max_old_space_size=5120' + NODE_OPTIONS: '--max_old_space_size=2048' run: npm test - name: Regression env: diff --git a/package-lock.json b/package-lock.json index d6fee3219..d539410c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "chalk": "^5.3.0", "cheerio": "^1.0.0", "decache": "^4.6.2", + "expose-gc": "^1.0.0", "get-image-colors": "^4.0.1", "https-proxy-agent": "^7.0.5", "husky": "^9.1.5", @@ -7040,6 +7041,16 @@ "node": ">=4" } }, + "node_modules/expose-gc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/expose-gc/-/expose-gc-1.0.0.tgz", + "integrity": "sha512-ecOHrdm+zyOCGIwX18/1RHkUWgxDqGGRiGhaNC+42jReTtudbm2ID/DMa/wpaHwqy5YQHPZvsDqRM2F2iZ0uVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/ext-list": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", @@ -19598,6 +19609,12 @@ "pify": "^2.2.0" } }, + "expose-gc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/expose-gc/-/expose-gc-1.0.0.tgz", + "integrity": "sha512-ecOHrdm+zyOCGIwX18/1RHkUWgxDqGGRiGhaNC+42jReTtudbm2ID/DMa/wpaHwqy5YQHPZvsDqRM2F2iZ0uVA==", + "dev": true + }, "ext-list": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", diff --git a/package.json b/package.json index 6fdc2f1ff..84573a29b 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "chalk": "^5.3.0", "cheerio": "^1.0.0", "decache": "^4.6.2", + "expose-gc": "^1.0.0", "get-image-colors": "^4.0.1", "https-proxy-agent": "^7.0.5", "husky": "^9.1.5", diff --git a/test/index.spec.mjs b/test/index.spec.mjs index b5b6f27ea..c5e01475f 100755 --- a/test/index.spec.mjs +++ b/test/index.spec.mjs @@ -2,6 +2,7 @@ import assert from 'node:assert'; import { resolve } from 'node:path'; import { createRequire } from 'module'; +import gc from 'expose-gc/function.js'; import { expect } from 'chai'; import dedupe from '../build/dedupe.mjs'; @@ -14,8 +15,14 @@ let Items; let data; const inits = []; -const importFresh = async (path) => { - return (await import(`${path}?update=${Date.now()}`)).default; +/** + * Use for fresh imports + * @param {string} path to import + * @param {string?} discriminator extra query param to force cache bust + * @returns {Promise} + */ +const importFresh = async (path, discriminator) => { + return (await import(`${path}?discriminator=${discriminator}`)).default; }; const wrapConstr = async (opts) => { const before = Date.now(); @@ -27,26 +34,34 @@ const wrapConstr = async (opts) => { const namedExclusions = ['Excalibur Prime', 'Helminth']; -for (const base of ['index.js', 'index.mjs']) { +const setupItems = async () => { + Items = await importFresh(itemPath); + data = Object.freeze({ + items: await wrapConstr(), + warframes: await wrapConstr({ category: ['Warframes', 'Archwing'], i18n: 'en', i18nOnObject: true }), + weapons: await wrapConstr({ + category: ['Primary', 'Secondary', 'Melee', 'Arch-Melee', 'Arch-Gun'], + i18n: 'en', + i18nOnObject: true, + }), + }); +}; + +const test = (base) => { describe(base, () => { before(async () => { itemPath = resolve(`./${base}`); - Items = await importFresh(itemPath); - data = Object.freeze({ - items: await wrapConstr(), - warframes: await wrapConstr({ category: ['Warframes', 'Archwing'], i18n: 'en', i18nOnObject: true }), - weapons: await wrapConstr({ - category: ['Primary', 'Secondary', 'Melee', 'Arch-Melee', 'Arch-Gun'], - i18n: 'en', - i18nOnObject: true, - }), - }); + await setupItems(); }); beforeEach(async () => { - Items = await importFresh(itemPath); + gc(); + await setupItems(); }); afterEach(async () => { delete require.cache[itemPath]; + Items = undefined; + data = undefined; + gc(); }); it('should contain items when initializing.', async () => { const items = await wrapConstr(); @@ -86,7 +101,9 @@ for (const base of ['index.js', 'index.mjs']) { assert(primes.length < items.length); }); describe('i18n', () => { + beforeEach(gc); it('should populate with a truthy boolean', async () => { + Items = await importFresh(itemPath, Date.now()); const items = await wrapConstr({ category: ['Mods'], i18n: ['es', 'tr'] }); assert(!!items.i18n[items[0].uniqueName].tr); assert(!!items.i18n[items[0].uniqueName].es); @@ -108,6 +125,7 @@ for (const base of ['index.js', 'index.mjs']) { }); }); describe('drops', () => { + beforeEach(gc); it('should not have drops for hikou', async () => { const items = await wrapConstr({ category: ['Secondary'] }); const hikouMatches = items.filter((i) => i.name === 'Hikou'); @@ -157,6 +175,7 @@ for (const base of ['index.js', 'index.mjs']) { }); }); describe('integrity', async () => { + beforeEach(gc); it('weapons should only have 1 result for Mausolon', () => { const matches = data.weapons .filter((i) => i.name === 'Mausolon') @@ -302,4 +321,6 @@ for (const base of ['index.js', 'index.mjs']) { expect(helminth.abilities.length).lessThan(20); }); }); -} +}; + +['index.js', 'index.mjs'].forEach(test);