From 204a60d9c05690f2bda4cc67f3e103d998bfc389 Mon Sep 17 00:00:00 2001 From: Stuart Knightley Date: Tue, 14 Jun 2022 13:47:53 -0700 Subject: [PATCH 1/7] Add node perf test --- package-lock.json | 24 ++++++++++++++++++++++++ package.json | 2 ++ test/perf/.eslintrc.js | 8 ++++++++ test/perf/node.js | 7 +++++++ test/perf/perf.js | 26 ++++++++++++++++++++++++++ 5 files changed, 67 insertions(+) create mode 100644 test/perf/.eslintrc.js create mode 100644 test/perf/node.js create mode 100644 test/perf/perf.js diff --git a/package-lock.json b/package-lock.json index 298c6918..e6eef778 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5292,6 +5292,24 @@ "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", "dev": true }, + "benchmark": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", + "integrity": "sha1-CfPeMckWQl1JjMLuVloOvzwqVik=", + "dev": true, + "requires": { + "lodash": "^4.17.4", + "platform": "^1.3.3" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + } + } + }, "binary-extensions": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz", @@ -8142,6 +8160,12 @@ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", "dev": true }, + "platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", + "dev": true + }, "playwright": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.15.2.tgz", diff --git a/package.json b/package.json index 8e7a1da7..531b190d 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "test": "npm run test-node && npm run test-browser && tsc", "test-node": "qunit --require ./test/helpers/test-utils.js --require ./test/helpers/node-test-utils.js test/asserts/", "test-browser": "grunt build && node test/run.js", + "perf-node": "node test/perf/node.js", "lint": "eslint ." }, "contributors": [ @@ -39,6 +40,7 @@ "inflate" ], "devDependencies": { + "benchmark": "^2.1.4", "browserify": "~13.0.0", "eslint": "^8.18.0", "grunt": "~0.4.1", diff --git a/test/perf/.eslintrc.js b/test/perf/.eslintrc.js new file mode 100644 index 00000000..28835dd3 --- /dev/null +++ b/test/perf/.eslintrc.js @@ -0,0 +1,8 @@ +"use strict"; + +module.exports = { + globals: { + // Added by index.html and node.js + Benchmark: false, + }, +}; diff --git a/test/perf/node.js b/test/perf/node.js new file mode 100644 index 00000000..a1daa3be --- /dev/null +++ b/test/perf/node.js @@ -0,0 +1,7 @@ +"use strict"; + +globalThis.Benchmark = require("benchmark"); +globalThis.JSZip = require("../../lib/index"); + +const run = require("./perf"); +run("nodebuffer"); diff --git a/test/perf/perf.js b/test/perf/perf.js new file mode 100644 index 00000000..ee3355a7 --- /dev/null +++ b/test/perf/perf.js @@ -0,0 +1,26 @@ +"use strict"; + +module.exports = function (type) { + const suite = new Benchmark.Suite(); + + suite + .add("generateAsync", { + defer: true, + async fn(deferred) { + const zip = new JSZip(); + + for (let i = 0; i < 50; i++) { + zip.file("file_" + i, "R0lGODdhBQAFAIACAAAAAP/eACwAAAAABQAFAAACCIwPkWerClIBADs=", { base64: true, date: new Date(1234123491011) }); + } + + await zip.generateAsync({ type }); + deferred.resolve(); + } + }) + .on("cycle", event => { + // Output benchmark result by converting benchmark result to string + console.log(String(event.target)); + }) + .on("complete", () => console.log("Benchmark complete")) + .run({ "async": true }); +}; From 8d07f3c1885bf55db3f6775801691b774581585a Mon Sep 17 00:00:00 2001 From: Stuart Knightley Date: Tue, 14 Jun 2022 13:48:14 -0700 Subject: [PATCH 2/7] Refactor test runner for perf tests --- test/run.js | 59 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/test/run.js b/test/run.js index fe52d6de..1ea63ff4 100644 --- a/test/run.js +++ b/test/run.js @@ -23,20 +23,14 @@ const createServer = require("http-server").createServer; * @param {string} browserType * @returns {Promise<[string, Results]>} */ -async function run(browserType) { +async function runBrowser(browserType, waitFor, file) { console.log("Starting", browserType); const browser = await playwright[browserType].launch(); const context = await browser.newContext(); const page = await context.newPage(); - await page.goto("http://127.0.0.1:8080/test/index.html?hidepassed"); - - let result; - do { - result = await page.evaluate(() => { - return window.global_test_results; - }); - } while (!result); + await page.goto(`http://127.0.0.1:8080/test/${file}`); + const result = await waitFor(page); console.log("Closing", browserType); await browser.close(); @@ -44,7 +38,7 @@ async function run(browserType) { return [browserType, result]; } -async function main() { +async function runBrowsers(waitFor, file) { const browsersTypes = ["chromium", "firefox", "webkit"]; const server = createServer({root: path.join(__dirname, "..")}); @@ -52,23 +46,38 @@ async function main() { console.log("Server started"); try { - const results = await Promise.all(browsersTypes.map(run)); - - let failures = false; - for (const result of results) { - console.log(...result); - failures = failures || result[1].failed > 0; - } - - if (failures) { - console.log("Tests failed"); - process.exit(1); - } else { - console.log("Tests passed!"); - } + const results = await Promise.all(browsersTypes.map(b => runBrowser(b, waitFor, file))); + return results; } finally { server.close(); } } -main(); +async function waitForTests(page) { + let result; + do { + result = await page.evaluate(() => { + return window.global_test_results; + }); + } while (!result); + return result; +} + +async function runTests() { + const results = await runBrowsers(waitForTests, "index.html?hidepassed"); + + let failures = false; + for (const result of results) { + console.log(...result); + failures = failures || result[1].failed > 0; + } + + if (failures) { + console.log("Tests failed"); + process.exit(1); + } else { + console.log("Tests passed!"); + } +} + +runTests(); From 6f2474d600a848333ecf7ab33c3781c07d8f8b48 Mon Sep 17 00:00:00 2001 From: Stuart Knightley Date: Tue, 14 Jun 2022 14:14:03 -0700 Subject: [PATCH 3/7] Add perf/benchmark for browser --- package.json | 4 +++- test/perf/index.html | 16 +++++++++++++ test/perf/perf.js | 55 +++++++++++++++++++++++++++----------------- test/run.js | 35 +++++++++++++++++++++++++++- 4 files changed, 87 insertions(+), 23 deletions(-) create mode 100644 test/perf/index.html diff --git a/package.json b/package.json index 531b190d..f10e84d3 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,10 @@ "scripts": { "test": "npm run test-node && npm run test-browser && tsc", "test-node": "qunit --require ./test/helpers/test-utils.js --require ./test/helpers/node-test-utils.js test/asserts/", - "test-browser": "grunt build && node test/run.js", + "test-browser": "grunt build && node test/run.js --test", + "perf": "npm run perf-node && npm run perf-browser", "perf-node": "node test/perf/node.js", + "perf-browser": "node test/run.js --benchmark", "lint": "eslint ." }, "contributors": [ diff --git a/test/perf/index.html b/test/perf/index.html new file mode 100644 index 00000000..7dbcb750 --- /dev/null +++ b/test/perf/index.html @@ -0,0 +1,16 @@ + + + + + JSZip Performance + + + + + + + + + \ No newline at end of file diff --git a/test/perf/perf.js b/test/perf/perf.js index ee3355a7..30f00637 100644 --- a/test/perf/perf.js +++ b/test/perf/perf.js @@ -1,26 +1,39 @@ "use strict"; -module.exports = function (type) { - const suite = new Benchmark.Suite(); +(function (root, factory) { + if (typeof module === "object" && module.exports) { + module.exports = factory(); + } else { + root.benchmark = factory(); + } +}(typeof self !== "undefined" ? self : this, function () { + return function (type) { + return new Promise(resolve => { + const suite = new Benchmark.Suite(); - suite - .add("generateAsync", { - defer: true, - async fn(deferred) { - const zip = new JSZip(); + suite + .add(`${type} generateAsync`, { + defer: true, + async fn(deferred) { + const zip = new JSZip(); - for (let i = 0; i < 50; i++) { - zip.file("file_" + i, "R0lGODdhBQAFAIACAAAAAP/eACwAAAAABQAFAAACCIwPkWerClIBADs=", { base64: true, date: new Date(1234123491011) }); - } + for (let i = 0; i < 50; i++) { + zip.file("file_" + i, "R0lGODdhBQAFAIACAAAAAP/eACwAAAAABQAFAAACCIwPkWerClIBADs=", { base64: true, date: new Date(1234123491011) }); + } - await zip.generateAsync({ type }); - deferred.resolve(); - } - }) - .on("cycle", event => { - // Output benchmark result by converting benchmark result to string - console.log(String(event.target)); - }) - .on("complete", () => console.log("Benchmark complete")) - .run({ "async": true }); -}; + await zip.generateAsync({ type }); + deferred.resolve(); + } + }) + .on("cycle", event => { + // Output benchmark result by converting benchmark result to string + console.log(String(event.target)); + }) + .on("complete", () => { + console.log("Benchmark complete"); + resolve(); + }) + .run({ "async": true }); + }); + }; +})); diff --git a/test/run.js b/test/run.js index 1ea63ff4..7300e970 100644 --- a/test/run.js +++ b/test/run.js @@ -80,4 +80,37 @@ async function runTests() { } } -runTests(); +async function waitForBenchmark(page) { + return new Promise(resolve => { + const logs = []; + + page.on("console", async message => { + if (message.text() === "Benchmark complete") { + resolve(logs); + } else { + logs.push(message.text()); + } + }); + }); +} + +async function runBenchmark() { + const results = await runBrowsers(waitForBenchmark, "perf/index.html"); + + for (const [browser, logs] of results) { + for (const log of logs) { + console.log(browser, log); + } + } +} + +switch (process.argv[2]) { +case "--test": + runTests(); + break; +case "--benchmark": + runBenchmark(); + break; +default: + throw new Error(`Unknown argument: ${process.argv[2]}`); +} From da96cb507d0faa7229b3b007d455ef2705aae61c Mon Sep 17 00:00:00 2001 From: Stuart Knightley Date: Tue, 14 Jun 2022 17:18:16 -0700 Subject: [PATCH 4/7] Update actions/cache to v3 --- .github/workflows/pr.yaml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index f2502045..44a22a6f 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -18,19 +18,15 @@ jobs: cache: 'npm' - name: Cache Node modules - uses: actions/cache@v2 - env: - cache-name: cache-node-modules + uses: actions/cache@v3 + id: npm-cache with: - # npm cache files are stored in `~/.npm` on Linux/macOS path: ~/.npm - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }} + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: | - ${{ runner.os }}-build-${{ env.cache-name }}- - ${{ runner.os }}-build- - ${{ runner.os }}- + ${{ runner.os }}-node- - - name: "Install dependencies" + - name: Install dependencies run: | npm install sudo npx playwright install-deps From aa67068b1a0e81d6263b6a3cb59012cc1ce72b9a Mon Sep 17 00:00:00 2001 From: Stuart Knightley Date: Tue, 14 Jun 2022 17:22:30 -0700 Subject: [PATCH 5/7] Align on "benchmark" instead of "perf" --- package.json | 6 +++--- test/{perf => benchmark}/.eslintrc.js | 0 test/{perf/perf.js => benchmark/benchmark.js} | 0 test/{perf => benchmark}/index.html | 4 ++-- test/{perf => benchmark}/node.js | 4 ++-- test/run.js | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) rename test/{perf => benchmark}/.eslintrc.js (100%) rename test/{perf/perf.js => benchmark/benchmark.js} (100%) rename test/{perf => benchmark}/index.html (83%) rename test/{perf => benchmark}/node.js (61%) diff --git a/package.json b/package.json index f10e84d3..25f74b67 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,9 @@ "test": "npm run test-node && npm run test-browser && tsc", "test-node": "qunit --require ./test/helpers/test-utils.js --require ./test/helpers/node-test-utils.js test/asserts/", "test-browser": "grunt build && node test/run.js --test", - "perf": "npm run perf-node && npm run perf-browser", - "perf-node": "node test/perf/node.js", - "perf-browser": "node test/run.js --benchmark", + "benchmark": "npm run benchmark-node && npm run benchmark-browser", + "benchmark-node": "node test/benchmark/node.js", + "benchmark-browser": "node test/run.js --benchmark", "lint": "eslint ." }, "contributors": [ diff --git a/test/perf/.eslintrc.js b/test/benchmark/.eslintrc.js similarity index 100% rename from test/perf/.eslintrc.js rename to test/benchmark/.eslintrc.js diff --git a/test/perf/perf.js b/test/benchmark/benchmark.js similarity index 100% rename from test/perf/perf.js rename to test/benchmark/benchmark.js diff --git a/test/perf/index.html b/test/benchmark/index.html similarity index 83% rename from test/perf/index.html rename to test/benchmark/index.html index 7dbcb750..df2b699c 100644 --- a/test/perf/index.html +++ b/test/benchmark/index.html @@ -2,13 +2,13 @@ - JSZip Performance + JSZip Benchmark - + diff --git a/test/perf/node.js b/test/benchmark/node.js similarity index 61% rename from test/perf/node.js rename to test/benchmark/node.js index a1daa3be..8b359596 100644 --- a/test/perf/node.js +++ b/test/benchmark/node.js @@ -3,5 +3,5 @@ globalThis.Benchmark = require("benchmark"); globalThis.JSZip = require("../../lib/index"); -const run = require("./perf"); -run("nodebuffer"); +const benchmark = require("./benchmark"); +benchmark("nodebuffer"); diff --git a/test/run.js b/test/run.js index 7300e970..d2993cda 100644 --- a/test/run.js +++ b/test/run.js @@ -95,7 +95,7 @@ async function waitForBenchmark(page) { } async function runBenchmark() { - const results = await runBrowsers(waitForBenchmark, "perf/index.html"); + const results = await runBrowsers(waitForBenchmark, "benchmark/index.html"); for (const [browser, logs] of results) { for (const log of logs) { From 3b1f8b7c221a3771a2aba10dabf198f2bf0078c9 Mon Sep 17 00:00:00 2001 From: Stuart Knightley Date: Tue, 14 Jun 2022 17:22:41 -0700 Subject: [PATCH 6/7] Add benchmark to PR workflow --- .github/workflows/pr.yaml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 44a22a6f..ba6d24c5 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -35,3 +35,24 @@ jobs: run: npm run lint - name: Test run: npm test + + - name: Benchmark + run: npm run benchmark | tee benchmark.txt + + - name: Download previous benchmark data + uses: actions/cache@v3 + with: + path: ./cache + key: ${{ runner.os }}-benchmark + + - name: Store benchmark result + uses: benchmark-action/github-action-benchmark@v1 + with: + tool: 'benchmarkjs' + output-file-path: benchmark.txt + external-data-json-path: ./cache/benchmark-data.json + github-token: ${{ secrets.GITHUB_TOKEN }} + alert-threshold: '150%' + comment-on-alert: true + fail-on-alert: true + alert-comment-cc-users: '@Stuk' From 53a4f141d29bc650b3fdd02f91b16d267e990675 Mon Sep 17 00:00:00 2001 From: Stuart Knightley Date: Tue, 14 Jun 2022 17:28:40 -0700 Subject: [PATCH 7/7] Add trailing newlines --- test/benchmark/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmark/index.html b/test/benchmark/index.html index df2b699c..0f92fe1f 100644 --- a/test/benchmark/index.html +++ b/test/benchmark/index.html @@ -13,4 +13,4 @@ benchmark("arraybuffer"); - \ No newline at end of file +