Skip to content

Commit caefbc0

Browse files
authored
Merge pull request #834 from Stuk/benchmark
Add benchmark/performance tests
2 parents 260e68a + 53a4f14 commit caefbc0

File tree

8 files changed

+191
-34
lines changed

8 files changed

+191
-34
lines changed

.github/workflows/pr.yaml

+26-9
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,15 @@ jobs:
1818
cache: 'npm'
1919

2020
- name: Cache Node modules
21-
uses: actions/cache@v2
22-
env:
23-
cache-name: cache-node-modules
21+
uses: actions/cache@v3
22+
id: npm-cache
2423
with:
25-
# npm cache files are stored in `~/.npm` on Linux/macOS
2624
path: ~/.npm
27-
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
25+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
2826
restore-keys: |
29-
${{ runner.os }}-build-${{ env.cache-name }}-
30-
${{ runner.os }}-build-
31-
${{ runner.os }}-
27+
${{ runner.os }}-node-
3228
33-
- name: "Install dependencies"
29+
- name: Install dependencies
3430
run: |
3531
npm install
3632
sudo npx playwright install-deps
@@ -39,3 +35,24 @@ jobs:
3935
run: npm run lint
4036
- name: Test
4137
run: npm test
38+
39+
- name: Benchmark
40+
run: npm run benchmark | tee benchmark.txt
41+
42+
- name: Download previous benchmark data
43+
uses: actions/cache@v3
44+
with:
45+
path: ./cache
46+
key: ${{ runner.os }}-benchmark
47+
48+
- name: Store benchmark result
49+
uses: benchmark-action/github-action-benchmark@v1
50+
with:
51+
tool: 'benchmarkjs'
52+
output-file-path: benchmark.txt
53+
external-data-json-path: ./cache/benchmark-data.json
54+
github-token: ${{ secrets.GITHUB_TOKEN }}
55+
alert-threshold: '150%'
56+
comment-on-alert: true
57+
fail-on-alert: true
58+
alert-comment-cc-users: '@Stuk'

package-lock.json

+24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
"scripts": {
77
"test": "npm run test-node && npm run test-browser && tsc",
88
"test-node": "qunit --require ./test/helpers/test-utils.js --require ./test/helpers/node-test-utils.js test/asserts/",
9-
"test-browser": "grunt build && node test/run.js",
9+
"test-browser": "grunt build && node test/run.js --test",
10+
"benchmark": "npm run benchmark-node && npm run benchmark-browser",
11+
"benchmark-node": "node test/benchmark/node.js",
12+
"benchmark-browser": "node test/run.js --benchmark",
1013
"lint": "eslint ."
1114
},
1215
"contributors": [
@@ -39,6 +42,7 @@
3942
"inflate"
4043
],
4144
"devDependencies": {
45+
"benchmark": "^2.1.4",
4246
"browserify": "~13.0.0",
4347
"eslint": "^8.18.0",
4448
"grunt": "~0.4.1",

test/benchmark/.eslintrc.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"use strict";
2+
3+
module.exports = {
4+
globals: {
5+
// Added by index.html and node.js
6+
Benchmark: false,
7+
},
8+
};

test/benchmark/benchmark.js

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"use strict";
2+
3+
(function (root, factory) {
4+
if (typeof module === "object" && module.exports) {
5+
module.exports = factory();
6+
} else {
7+
root.benchmark = factory();
8+
}
9+
}(typeof self !== "undefined" ? self : this, function () {
10+
return function (type) {
11+
return new Promise(resolve => {
12+
const suite = new Benchmark.Suite();
13+
14+
suite
15+
.add(`${type} generateAsync`, {
16+
defer: true,
17+
async fn(deferred) {
18+
const zip = new JSZip();
19+
20+
for (let i = 0; i < 50; i++) {
21+
zip.file("file_" + i, "R0lGODdhBQAFAIACAAAAAP/eACwAAAAABQAFAAACCIwPkWerClIBADs=", { base64: true, date: new Date(1234123491011) });
22+
}
23+
24+
await zip.generateAsync({ type });
25+
deferred.resolve();
26+
}
27+
})
28+
.on("cycle", event => {
29+
// Output benchmark result by converting benchmark result to string
30+
console.log(String(event.target));
31+
})
32+
.on("complete", () => {
33+
console.log("Benchmark complete");
34+
resolve();
35+
})
36+
.run({ "async": true });
37+
});
38+
};
39+
}));

test/benchmark/index.html

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
5+
<title>JSZip Benchmark</title>
6+
</head>
7+
<body>
8+
<script src="../../node_modules/benchmark/node_modules/lodash/lodash.js"></script>
9+
<script src="../../node_modules/benchmark/benchmark.js"></script>
10+
<script src="../../dist/jszip.js"></script>
11+
<script src="./benchmark.js"></script>
12+
<script>
13+
benchmark("arraybuffer");
14+
</script>
15+
</body>
16+
</html>

test/benchmark/node.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"use strict";
2+
3+
globalThis.Benchmark = require("benchmark");
4+
globalThis.JSZip = require("../../lib/index");
5+
6+
const benchmark = require("./benchmark");
7+
benchmark("nodebuffer");

test/run.js

+66-24
Original file line numberDiff line numberDiff line change
@@ -23,52 +23,94 @@ const createServer = require("http-server").createServer;
2323
* @param {string} browserType
2424
* @returns {Promise<[string, Results]>}
2525
*/
26-
async function run(browserType) {
26+
async function runBrowser(browserType, waitFor, file) {
2727
console.log("Starting", browserType);
2828
const browser = await playwright[browserType].launch();
2929
const context = await browser.newContext();
3030
const page = await context.newPage();
3131

32-
await page.goto("http://127.0.0.1:8080/test/index.html?hidepassed");
33-
34-
let result;
35-
do {
36-
result = await page.evaluate(() => {
37-
return window.global_test_results;
38-
});
39-
} while (!result);
32+
await page.goto(`http://127.0.0.1:8080/test/${file}`);
33+
const result = await waitFor(page);
4034

4135
console.log("Closing", browserType);
4236
await browser.close();
4337

4438
return [browserType, result];
4539
}
4640

47-
async function main() {
41+
async function runBrowsers(waitFor, file) {
4842
const browsersTypes = ["chromium", "firefox", "webkit"];
4943

5044
const server = createServer({root: path.join(__dirname, "..")});
5145
await new Promise(resolve => server.listen(8080, "127.0.0.1", resolve));
5246
console.log("Server started");
5347

5448
try {
55-
const results = await Promise.all(browsersTypes.map(run));
49+
const results = await Promise.all(browsersTypes.map(b => runBrowser(b, waitFor, file)));
50+
return results;
51+
} finally {
52+
server.close();
53+
}
54+
}
5655

57-
let failures = false;
58-
for (const result of results) {
59-
console.log(...result);
60-
failures = failures || result[1].failed > 0;
61-
}
56+
async function waitForTests(page) {
57+
let result;
58+
do {
59+
result = await page.evaluate(() => {
60+
return window.global_test_results;
61+
});
62+
} while (!result);
63+
return result;
64+
}
65+
66+
async function runTests() {
67+
const results = await runBrowsers(waitForTests, "index.html?hidepassed");
68+
69+
let failures = false;
70+
for (const result of results) {
71+
console.log(...result);
72+
failures = failures || result[1].failed > 0;
73+
}
74+
75+
if (failures) {
76+
console.log("Tests failed");
77+
process.exit(1);
78+
} else {
79+
console.log("Tests passed!");
80+
}
81+
}
6282

63-
if (failures) {
64-
console.log("Tests failed");
65-
process.exit(1);
66-
} else {
67-
console.log("Tests passed!");
83+
async function waitForBenchmark(page) {
84+
return new Promise(resolve => {
85+
const logs = [];
86+
87+
page.on("console", async message => {
88+
if (message.text() === "Benchmark complete") {
89+
resolve(logs);
90+
} else {
91+
logs.push(message.text());
92+
}
93+
});
94+
});
95+
}
96+
97+
async function runBenchmark() {
98+
const results = await runBrowsers(waitForBenchmark, "benchmark/index.html");
99+
100+
for (const [browser, logs] of results) {
101+
for (const log of logs) {
102+
console.log(browser, log);
68103
}
69-
} finally {
70-
server.close();
71104
}
72105
}
73106

74-
main();
107+
switch (process.argv[2]) {
108+
case "--test":
109+
runTests();
110+
break;
111+
case "--benchmark":
112+
runBenchmark();
113+
break;
114+
default:
115+
throw new Error(`Unknown argument: ${process.argv[2]}`);
116+
}

0 commit comments

Comments
 (0)