Skip to content

perf(ext/node): cache compiled glob matchers + bump bundled minimatch to 10.2.5#35873

Merged
bartlomieju merged 1 commit into
mainfrom
perf/node-matchesglob-cache
Jul 9, 2026
Merged

perf(ext/node): cache compiled glob matchers + bump bundled minimatch to 10.2.5#35873
bartlomieju merged 1 commit into
mainfrom
perf/node-matchesglob-cache

Conversation

@bartlomieju

Copy link
Copy Markdown
Member

matchGlobPattern (backing path.matchesGlob and glob matching) recompiled a Minimatch object — building a regex — on every call; this caches the compiled matcher per pattern (bounded, per-platform). The bundled minimatch was also regenerated from 10.0.1 → 10.2.5, which fixes a ~3× .match() perf regression. Net result: node:path.matchesGlob goes from ~2.19µs to ~495ns.

Benchmarked on macOS arm64, node:path.matchesGlob:

Pattern Node 26.4.0 Node 27.0.0-pre Deno (this PR) Speedup vs N27-pre
long path **/*.js 1.43 µs 1.45 µs 468 ns 3.1×
simple *.js (hit) 995 ns 1.00 µs 61 ns 16×
simple *.js (miss) 993 ns 1.03 µs 60 ns 17×
nested a/**/b.ts 1.52 µs 1.52 µs 181 ns 8.4×
extglob *.{js,ts} 3.86 µs 3.88 µs 115 ns 34×
char class [a-z]*.js 1.26 µs 1.23 µs 79 ns 16×

… to 10.2.5

matchGlobPattern (used by path.matchesGlob and fs glob matching) rebuilt a
Minimatch object — compiling the pattern to a regex — on every call. Cache the
compiled matcher per pattern (per-platform maps, bounded at 256) so repeated
calls reuse it.

Also regenerate the bundled minimatch: 10.0.1 had a ~3x .match() perf
regression that upstream fixed in 10.2.5.

node:path.matchesGlob: ~2.19us -> ~495ns on a long path.
@bartlomieju
bartlomieju enabled auto-merge (squash) July 9, 2026 08:49
@bartlomieju
bartlomieju merged commit d1c3b93 into main Jul 9, 2026
398 of 403 checks passed
@bartlomieju
bartlomieju deleted the perf/node-matchesglob-cache branch July 9, 2026 08:50
bartlomieju added a commit that referenced this pull request Jul 15, 2026
… to 10.2.5 (#35873)

`matchGlobPattern` (backing `path.matchesGlob` and glob matching)
recompiled a `Minimatch` object — building a regex — on every call; this
caches the compiled matcher per pattern (bounded, per-platform). The
bundled minimatch was also regenerated from 10.0.1 → 10.2.5, which fixes
a ~3× `.match()` perf regression. Net result: `node:path.matchesGlob`
goes from ~2.19µs to ~495ns.

Benchmarked on macOS arm64, `node:path.matchesGlob`:

| Pattern | Node 26.4.0 | Node 27.0.0-pre | **Deno (this PR)** | Speedup
vs N27-pre |
|---|---|---|---|---|
| long path `**/*.js` | 1.43 µs | 1.45 µs | **468 ns** | **3.1×** |
| simple `*.js` (hit) | 995 ns | 1.00 µs | **61 ns** | **16×** |
| simple `*.js` (miss) | 993 ns | 1.03 µs | **60 ns** | **17×** |
| nested `a/**/b.ts` | 1.52 µs | 1.52 µs | **181 ns** | **8.4×** |
| extglob `*.{js,ts}` | 3.86 µs | 3.88 µs | **115 ns** | **34×** |
| char class `[a-z]*.js` | 1.26 µs | 1.23 µs | **79 ns** | **16×** |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant