Skip to content

Commit 33d6e25

Browse files
authored
perf(utils): setup microbenchmark for crawlFileSystem (#355)
1 parent 5d70e4d commit 33d6e25

File tree

12 files changed

+151
-125
lines changed

12 files changed

+151
-125
lines changed

packages/utils/perf/README.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Micro Benchmarks
2+
3+
Execute any benchmark by running `nx run utils:perf` naming the folder e.g. `nx run utils:perf score-report`.
4+
5+
To list benchmarks run `ls -l | grep "^d" | awk '{print $9}'`
6+
7+
## scoreReport
8+
9+
`nx run utils:perf score-report`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import * as Benchmark from 'benchmark';
2+
import { join } from 'path';
3+
import {
4+
CrawlFileSystemOptions,
5+
crawlFileSystem,
6+
} from '../../src/lib/file-system';
7+
import { crawlFileSystemOptimized0 } from './optimized0';
8+
9+
const PROCESS_ARGUMENT_TARGET_DIRECTORY = String(
10+
process.argv
11+
.find(arg => arg.startsWith('--directory'))
12+
?.split('=')
13+
.pop() || '',
14+
);
15+
const PROCESS_ARGUMENT_PATTERN = String(
16+
process.argv
17+
.find(arg => arg.startsWith('--pattern'))
18+
?.split('=')
19+
.pop() || '',
20+
);
21+
22+
const suite = new Benchmark.Suite('report-scoring');
23+
24+
const TARGET_DIRECTORY =
25+
PROCESS_ARGUMENT_TARGET_DIRECTORY ||
26+
join(process.cwd(), '..', '..', '..', 'node_modules');
27+
const PATTERN = PROCESS_ARGUMENT_PATTERN || /.json$/;
28+
29+
// ==================
30+
31+
const start = performance.now();
32+
33+
// Add listener
34+
const listeners = {
35+
cycle: function (event: Benchmark.Event) {
36+
console.info(String(event.target));
37+
},
38+
complete: () => {
39+
if (typeof suite.filter === 'function') {
40+
console.info(' ');
41+
console.info(
42+
`Total Duration: ${((performance.now() - start) / 1000).toFixed(
43+
2,
44+
)} sec`,
45+
);
46+
console.info('Fastest is ' + suite.filter('fastest').map('name'));
47+
}
48+
},
49+
};
50+
51+
// ==================
52+
53+
// Add tests
54+
const options = {
55+
directory: TARGET_DIRECTORY,
56+
pattern: PATTERN,
57+
};
58+
suite.add('Base', wrapWithDefer(crawlFileSystem));
59+
suite.add('Optimized 0', wrapWithDefer(crawlFileSystemOptimized0));
60+
61+
// ==================
62+
63+
// Add Listener
64+
Object.entries(listeners).forEach(([name, fn]) => {
65+
suite.on(name, fn);
66+
});
67+
68+
// ==================
69+
70+
console.info('You can adjust the test with the following arguments:');
71+
console.info(
72+
`directory target directory of test --directory=${TARGET_DIRECTORY}`,
73+
);
74+
console.info(
75+
`pattern pattern to search --pattern=${PATTERN}`,
76+
);
77+
console.info(' ');
78+
console.info('Start benchmark...');
79+
console.info(' ');
80+
81+
suite.run({
82+
async: true,
83+
});
84+
85+
// ==============================================================
86+
87+
function wrapWithDefer<T>(
88+
asyncFn: (options: CrawlFileSystemOptions<T>) => Promise<unknown[]>,
89+
) {
90+
return {
91+
defer: true, // important for async functions
92+
fn: function (deferred: { resolve: () => void }) {
93+
return asyncFn(options)
94+
.catch(() => [])
95+
.then((result: unknown[]) => {
96+
if (result.length === 0) {
97+
throw new Error(`Result length is ${result.length}`);
98+
} else {
99+
deferred.resolve();
100+
}
101+
return void 0;
102+
});
103+
},
104+
};
105+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { CrawlFileSystemOptions } from '../../src';
2+
3+
export function crawlFileSystemOptimized0<T = string>(
4+
options: CrawlFileSystemOptions<T>,
5+
): Promise<T[]> {
6+
const { directory, pattern: needle = '@TODO' } = options;
7+
return Promise.resolve([directory, needle] as T[]);
8+
}

packages/utils/perf/implementations/base.ts

-106
This file was deleted.

packages/utils/perf/index.ts renamed to packages/utils/perf/score-report/index.ts

+13-15
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import * as Benchmark from 'benchmark';
22
import { Report } from '@code-pushup/models';
3-
import { scoreReport } from './implementations/base';
4-
import { scoreReportOptimized0 } from './implementations/optimized0';
5-
import { scoreReportOptimized1 } from './implementations/optimized1';
6-
import { scoreReportOptimized2 } from './implementations/optimized2';
7-
import { scoreReportOptimized3 } from './implementations/optimized3';
3+
import { scoreReport } from '../../src/lib/scoring';
4+
import { scoreReportOptimized0 } from './optimized0';
5+
import { scoreReportOptimized1 } from './optimized1';
6+
import { scoreReportOptimized2 } from './optimized2';
7+
import { scoreReportOptimized3 } from './optimized3';
88

99
interface MinimalReportOptions {
1010
numAuditsP1?: number;
@@ -66,7 +66,7 @@ const listeners = {
6666
// ==================
6767

6868
// Add tests
69-
suite.add('scoreReport', _scoreReport);
69+
suite.add('scoreReport', scoreReport);
7070
suite.add('scoreReportOptimized0', _scoreReportOptimized0);
7171
suite.add('scoreReportOptimized1', _scoreReportOptimized1);
7272
suite.add('scoreReportOptimized2', _scoreReportOptimized2);
@@ -97,18 +97,16 @@ console.info(' ');
9797

9898
const start = performance.now();
9999

100-
suite.run();
101-
102-
console.info(
103-
`Total Duration: ${((performance.now() - start) / 1000).toFixed(2)} sec`,
104-
);
100+
suite.run({
101+
onComplete: () => {
102+
console.info(
103+
`Total Duration: ${((performance.now() - start) / 1000).toFixed(2)} sec`,
104+
);
105+
},
106+
});
105107

106108
// ==============================================================
107109

108-
function _scoreReport() {
109-
scoreReport(minimalReport());
110-
}
111-
112110
function _scoreReportOptimized0() {
113111
scoreReportOptimized0(minimalReport());
114112
}

packages/utils/project.json

+10-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,16 @@
3030
}
3131
},
3232
"perf": {
33-
"command": "npx tsx ./packages/utils/perf --tsconfig=packages/utils/tsconfig.perf.json"
33+
"command": "npx tsx --tsconfig=../tsconfig.perf.json",
34+
"options": {
35+
"cwd": "./packages/utils/perf"
36+
}
37+
},
38+
"perf:list": {
39+
"command": "ls -l | grep \"^d\" | awk '{print $9}'",
40+
"options": {
41+
"cwd": "./packages/utils/perf"
42+
}
3443
},
3544
"unit-test": {
3645
"executor": "@nx/vite:test",

packages/utils/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export {
1010
export {
1111
FileResult,
1212
MultipleFileResults,
13+
CrawlFileSystemOptions,
1314
crawlFileSystem,
1415
ensureDirectoryExists,
1516
fileExists,

packages/utils/src/lib/file-system.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,14 @@ export async function importEsmModule<T = unknown>(
101101
export function pluginWorkDir(slug: string): string {
102102
return join('node_modules', '.code-pushup', slug);
103103
}
104-
105-
export async function crawlFileSystem<T = string>(options: {
104+
export type CrawlFileSystemOptions<T> = {
106105
directory: string;
107106
pattern?: string | RegExp;
108107
fileTransform?: (filePath: string) => Promise<T> | T;
109-
}): Promise<T[]> {
108+
};
109+
export async function crawlFileSystem<T = string>(
110+
options: CrawlFileSystemOptions<T>,
111+
): Promise<T[]> {
110112
const {
111113
directory,
112114
pattern,

0 commit comments

Comments
 (0)