Skip to content

Commit 22a5d5a

Browse files
committed
chore: introduce native glob benchmark
1 parent bbc7d07 commit 22a5d5a

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

src/benchmark/suites/product/async.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as bencho from 'bencho';
44

55
import * as utils from '../../utils';
66

7-
type GlobImplementation = 'fast-glob' | 'node-glob' | 'tinyglobby';
7+
type GlobImplementation = 'fast-glob' | 'native' | 'node-glob' | 'tinyglobby';
88
// eslint-disable-next-line @typescript-eslint/no-explicit-any
99
type GlobImplFunction = (...args: any[]) => Promise<unknown[]>;
1010

@@ -17,6 +17,32 @@ class Glob {
1717
this.#pattern = pattern;
1818
}
1919

20+
/**
21+
* Assumptions:
22+
*
23+
* 1. The implementation returns entries with an absolute path, while all other solutions return a relative path.
24+
*/
25+
public async measureNative(): Promise<void> {
26+
const glob = await utils.importAndMeasure(utils.importNativeGlob);
27+
28+
await this.#measure(async () => {
29+
const iterator = await glob.glob(this.#pattern, {
30+
cwd: this.#cwd,
31+
withFileTypes: true,
32+
});
33+
34+
const entries: string[] = [];
35+
36+
for await (const dirent of iterator) {
37+
if (!dirent.isDirectory()) {
38+
entries.push(`${dirent.parentPath}/${dirent.name}`);
39+
}
40+
}
41+
42+
return entries;
43+
});
44+
}
45+
2046
public async measureNodeGlob(): Promise<void> {
2147
const glob = await utils.importAndMeasure(utils.importNodeGlob);
2248

@@ -71,6 +97,11 @@ class Glob {
7197
const glob = new Glob(cwd, pattern);
7298

7399
switch (impl) {
100+
case 'native': {
101+
await glob.measureNative();
102+
break;
103+
}
104+
74105
case 'node-glob': {
75106
await glob.measureNodeGlob();
76107
break;

src/benchmark/suites/product/sync.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as bencho from 'bencho';
44

55
import * as utils from '../../utils';
66

7-
type GlobImplementation = 'fast-glob' | 'node-glob' | 'tinyglobby';
7+
type GlobImplementation = 'fast-glob' | 'native' | 'node-glob' | 'tinyglobby';
88
// eslint-disable-next-line @typescript-eslint/no-explicit-any
99
type GlobImplFunction = (...args: any[]) => unknown[];
1010

@@ -17,6 +17,32 @@ class Glob {
1717
this.#pattern = pattern;
1818
}
1919

20+
/**
21+
* Assumptions:
22+
*
23+
* 1. The implementation returns entries with an absolute path, while all other solutions return a relative path.
24+
*/
25+
public async measureNative(): Promise<void> {
26+
const glob = await utils.importAndMeasure(utils.importNativeGlob);
27+
28+
this.#measure(() => {
29+
const iterator = glob.globSync(this.#pattern, {
30+
cwd: this.#cwd,
31+
withFileTypes: true,
32+
});
33+
34+
const entries: string[] = [];
35+
36+
for (const dirent of iterator) {
37+
if (!dirent.isDirectory()) {
38+
entries.push(`${dirent.parentPath}/${dirent.name}`);
39+
}
40+
}
41+
42+
return entries;
43+
});
44+
}
45+
2046
public async measureNodeGlob(): Promise<void> {
2147
const glob = await utils.importAndMeasure(utils.importNodeGlob);
2248

@@ -71,6 +97,11 @@ class Glob {
7197
const glob = new Glob(cwd, pattern);
7298

7399
switch (impl) {
100+
case 'native': {
101+
await glob.measureNative();
102+
break;
103+
}
104+
74105
case 'node-glob': {
75106
await glob.measureNodeGlob();
76107
break;

src/benchmark/utils.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,22 @@ import { performance } from 'node:perf_hooks';
22

33
import * as bencho from 'bencho';
44

5+
import type * as fs from 'node:fs';
56
import type * as currentVersion from '..';
67
import type * as previousVersion from 'fast-glob';
78
import type * as glob from 'glob';
89
import type * as tg from 'tinyglobby';
910

11+
type NativeGlobAsynchronous = (pattern: string, options: {
12+
cwd: string;
13+
withFileTypes: boolean;
14+
}) => Promise<AsyncIterable<fs.Dirent>>;
15+
16+
type NativeGlobSynchronous = (pattern: string, options: {
17+
cwd: string;
18+
withFileTypes: boolean;
19+
}) => fs.Dirent[];
20+
1021
export function timeStart(): number {
1122
return performance.now();
1223
}
@@ -23,6 +34,20 @@ export function importCurrentFastGlob(): Promise<typeof currentVersion> {
2334
return import('..');
2435
}
2536

37+
export async function importNativeGlob(): Promise<{
38+
glob: NativeGlobAsynchronous;
39+
globSync: NativeGlobSynchronous;
40+
}> {
41+
const fs = await import('node:fs');
42+
43+
return {
44+
// @ts-expect-error The current version of @types/node has not definitions for this method.
45+
glob: fs.promises.glob as NativeGlobAsynchronous,
46+
// @ts-expect-error The current version of @types/node has not definitions for this method.
47+
globSync: fs.globSync as NativeGlobSynchronous,
48+
};
49+
}
50+
2651
export function importPreviousFastGlob(): Promise<typeof previousVersion> {
2752
return import('fast-glob');
2853
}

0 commit comments

Comments
 (0)