Skip to content

Commit 667cccf

Browse files
7amed3liclemgbld
andauthored
feat: implement benchmarks using mitata (#496)
* feat: implement benchmarks using mitata * chore: add changeset * chore: add performance benchmarks using mitata - Add benchmarking infrastructure in workspaces/js-x-ray/benchmark - Use Node.js type stripping (requires Node >= 22) * chore: consolidate benchmarks into index.ts and move docs to root README * chore: use import.meta.dirname & move benchmark docs to end of README * chore: remove redundant run options in benchmarks * chore: implement file size thresholds for benchmark selection * chore: benchmark all files in size categories * Update README.md Co-authored-by: Clement Gombauld <[email protected]> --------- Co-authored-by: Clement Gombauld <[email protected]>
1 parent 1c2c39f commit 667cccf

File tree

4 files changed

+103
-2
lines changed

4 files changed

+103
-2
lines changed

.changeset/benchmark-mitata.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@nodesecure/js-x-ray": patch
3+
---
4+
5+
feat: add performance benchmarks using mitata

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ Alternatively, you can use `EntryFilesAnalyser` directly for multi-file analysis
115115
- [EntryFilesAnalyser](./workspaces/js-x-ray/docs/EntryFilesAnalyser.md)
116116
- [CollectableSet](./workspaces/js-x-ray/docs/CollectableSet.md)
117117

118+
118119
## Warnings
119120

120121
```ts
@@ -254,6 +255,14 @@ $ npm i @nodesecure/estree-ast-util
254255
$ yarn add @nodesecure/estree-ast-util
255256
```
256257

258+
## Benchmarks
259+
260+
The performance of js-x-ray is measured and tracked using [mitata](https://github.com/evanwashere/mitata).
261+
262+
To run the benchmarks:
263+
1. Navigate to `workspaces/js-x-ray`.
264+
2. Run `npm run bench`.
265+
257266
## Contributors ✨
258267

259268
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
2+
// Import Node.js Dependencies
3+
import { readFileSync, readdirSync } from "node:fs";
4+
import { join, resolve } from "node:path";
5+
6+
// Import Third-party Dependencies
7+
import { run, bench, group } from "mitata";
8+
9+
// Import Internal Dependencies
10+
import { AstAnalyser } from "../src/index.ts";
11+
12+
// Constants
13+
const EXAMPLES_DIR = resolve(import.meta.dirname, "../examples");
14+
15+
const KILOBYTE = 1024;
16+
const SMALL_THRESHOLD = 10 * KILOBYTE;
17+
const LARGE_THRESHOLD = 50 * KILOBYTE;
18+
19+
interface Fixture {
20+
name: string;
21+
content: string;
22+
size: number;
23+
}
24+
25+
function loadFixtures(): Fixture[] {
26+
const files = readdirSync(EXAMPLES_DIR);
27+
28+
return files.map((file) => {
29+
const path = join(EXAMPLES_DIR, file);
30+
const content = readFileSync(path, "utf-8");
31+
32+
return {
33+
name: file,
34+
content,
35+
size: content.length
36+
};
37+
});
38+
}
39+
40+
const fixtures = loadFixtures();
41+
const analyser = new AstAnalyser();
42+
43+
function formatFileSize(fixture: Fixture): string {
44+
return `${fixture.name} - ${(fixture.size / 1024).toFixed(2)}KB`;
45+
}
46+
47+
group("AstAnalyser.analyse()", () => {
48+
const sortedFixtures = [...fixtures].sort((a, b) => a.size - b.size);
49+
50+
const smallFixtures = sortedFixtures.filter((f) => f.size < SMALL_THRESHOLD);
51+
const mediumFixtures = sortedFixtures.filter((f) => f.size >= SMALL_THRESHOLD && f.size < LARGE_THRESHOLD);
52+
const largeFixtures = sortedFixtures.filter((f) => f.size >= LARGE_THRESHOLD);
53+
54+
for (const fixture of smallFixtures) {
55+
bench(`Small File (${formatFileSize(fixture)})`, () => {
56+
analyser.analyse(fixture.content);
57+
});
58+
}
59+
60+
for (const fixture of mediumFixtures) {
61+
bench(`Medium File (${formatFileSize(fixture)})`, () => {
62+
analyser.analyse(fixture.content);
63+
});
64+
}
65+
66+
for (const fixture of largeFixtures) {
67+
bench(`Large File (${formatFileSize(fixture)})`, () => {
68+
analyser.analyse(fixture.content);
69+
})
70+
// Large files might need GC between runs to be stable
71+
.gc("inner");
72+
}
73+
});
74+
75+
group("Obfuscated Code Analysis", () => {
76+
const obfuscated = fixtures.filter((f) => f.name.includes("obfuscate") || f.name.includes("jscrush"));
77+
78+
for (const fixture of obfuscated) {
79+
bench(`${fixture.name}`, () => {
80+
analyser.analyse(fixture.content);
81+
});
82+
}
83+
});
84+
85+
await run();

workspaces/js-x-ray/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"prepublishOnly": "npm run build",
2222
"build": "tsc",
2323
"test-only": "node --test-reporter=spec --test ./test/**/*.spec.ts",
24-
"test": "c8 --all --src ./src -r html npm run test-only"
24+
"test": "c8 --all --src ./src -r html npm run test-only",
25+
"bench": "node --expose-gc --experimental-strip-types ./benchmark/index.ts"
2526
},
2627
"publishConfig": {
2728
"registry": "https://registry.npmjs.org",
@@ -63,6 +64,7 @@
6364
"ts-pattern": "^5.0.6"
6465
},
6566
"devDependencies": {
66-
"astring": "1.9.0"
67+
"astring": "1.9.0",
68+
"mitata": "1.0.34"
6769
}
6870
}

0 commit comments

Comments
 (0)