diff --git a/src/benchmark/suites/product/async.ts b/src/benchmark/suites/product/async.ts index 404a15d1..b6bbd1cd 100644 --- a/src/benchmark/suites/product/async.ts +++ b/src/benchmark/suites/product/async.ts @@ -4,7 +4,7 @@ import * as bencho from 'bencho'; import * as utils from '../../utils'; -type GlobImplementation = 'fast-glob' | 'node-glob' | 'tinyglobby'; +type GlobImplementation = 'fast-glob' | 'native' | 'node-glob' | 'tinyglobby'; // eslint-disable-next-line @typescript-eslint/no-explicit-any type GlobImplFunction = (...args: any[]) => Promise; @@ -17,6 +17,32 @@ class Glob { this.#pattern = pattern; } + /** + * Assumptions: + * + * 1. The implementation returns entries with an absolute path, while all other solutions return a relative path. + */ + public async measureNative(): Promise { + const glob = await utils.importAndMeasure(utils.importNativeGlob); + + await this.#measure(async () => { + const iterator = await glob.glob(this.#pattern, { + cwd: this.#cwd, + withFileTypes: true, + }); + + const entries: string[] = []; + + for await (const dirent of iterator) { + if (!dirent.isDirectory()) { + entries.push(`${dirent.parentPath}/${dirent.name}`); + } + } + + return entries; + }); + } + public async measureNodeGlob(): Promise { const glob = await utils.importAndMeasure(utils.importNodeGlob); @@ -71,6 +97,11 @@ class Glob { const glob = new Glob(cwd, pattern); switch (impl) { + case 'native': { + await glob.measureNative(); + break; + } + case 'node-glob': { await glob.measureNodeGlob(); break; diff --git a/src/benchmark/suites/product/sync.ts b/src/benchmark/suites/product/sync.ts index d7f8000e..f66aff74 100644 --- a/src/benchmark/suites/product/sync.ts +++ b/src/benchmark/suites/product/sync.ts @@ -4,7 +4,7 @@ import * as bencho from 'bencho'; import * as utils from '../../utils'; -type GlobImplementation = 'fast-glob' | 'node-glob' | 'tinyglobby'; +type GlobImplementation = 'fast-glob' | 'native' | 'node-glob' | 'tinyglobby'; // eslint-disable-next-line @typescript-eslint/no-explicit-any type GlobImplFunction = (...args: any[]) => unknown[]; @@ -17,6 +17,32 @@ class Glob { this.#pattern = pattern; } + /** + * Assumptions: + * + * 1. The implementation returns entries with an absolute path, while all other solutions return a relative path. + */ + public async measureNative(): Promise { + const glob = await utils.importAndMeasure(utils.importNativeGlob); + + this.#measure(() => { + const iterator = glob.globSync(this.#pattern, { + cwd: this.#cwd, + withFileTypes: true, + }); + + const entries: string[] = []; + + for (const dirent of iterator) { + if (!dirent.isDirectory()) { + entries.push(`${dirent.parentPath}/${dirent.name}`); + } + } + + return entries; + }); + } + public async measureNodeGlob(): Promise { const glob = await utils.importAndMeasure(utils.importNodeGlob); @@ -71,6 +97,11 @@ class Glob { const glob = new Glob(cwd, pattern); switch (impl) { + case 'native': { + await glob.measureNative(); + break; + } + case 'node-glob': { await glob.measureNodeGlob(); break; diff --git a/src/benchmark/utils.ts b/src/benchmark/utils.ts index d0783a20..c60a90a5 100644 --- a/src/benchmark/utils.ts +++ b/src/benchmark/utils.ts @@ -2,11 +2,22 @@ import { performance } from 'node:perf_hooks'; import * as bencho from 'bencho'; +import type * as fs from 'node:fs'; import type * as currentVersion from '..'; import type * as previousVersion from 'fast-glob'; import type * as glob from 'glob'; import type * as tg from 'tinyglobby'; +type NativeGlobAsynchronous = (pattern: string, options: { + cwd: string; + withFileTypes: boolean; +}) => Promise>; + +type NativeGlobSynchronous = (pattern: string, options: { + cwd: string; + withFileTypes: boolean; +}) => fs.Dirent[]; + export function timeStart(): number { return performance.now(); } @@ -23,6 +34,20 @@ export function importCurrentFastGlob(): Promise { return import('..'); } +export async function importNativeGlob(): Promise<{ + glob: NativeGlobAsynchronous; + globSync: NativeGlobSynchronous; +}> { + const fs = await import('node:fs'); + + return { + // @ts-expect-error The current version of @types/node has not definitions for this method. + glob: fs.promises.glob as NativeGlobAsynchronous, + // @ts-expect-error The current version of @types/node has not definitions for this method. + globSync: fs.globSync as NativeGlobSynchronous, + }; +} + export function importPreviousFastGlob(): Promise { return import('fast-glob'); }