fs: implement glob natively - #65392
Conversation
|
Review requested:
|
|
cc @isaacs @nodejs/fs |
f172fce to
8bedc81
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #65392 +/- ##
==========================================
- Coverage 90.14% 89.71% -0.44%
==========================================
Files 752 764 +12
Lines 251870 254755 +2885
Branches 47365 48034 +669
==========================================
+ Hits 227037 228541 +1504
- Misses 16177 17147 +970
- Partials 8656 9067 +411
🚀 New features to boost your workflow:
|
I would feel more comfortable adopting one of those instead of having to maintain our own, have you explored that route? |
I have, but the perf wins here are dependent on this being in native, and not in JS:
I also think this can bring some improvements to things like the test runner. For instance, |
8bedc81 to
55e4ca3
Compare
Signed-off-by: avivkeller <me@aviv.sh>
|
(Whoops!) |
Ref: https://openjs-foundation.slack.com/archives/C019Y2T6STH/p1787069174254509
(AI assistance used to help port minimatch to C++ and take improvements from other implementations, e.g. Rust's fast-glob [oxc] and picomatch, etc).
I'd love some pretty pedantic reviews since this is substantial. It's 1:1 with the existing glob, so it's non-breaking, but please tear this apart just in case. This implementation is over 2x faster than the old one.
Benchmarking Result (`fs/bench-glob.js`)
When compared to existing tools "on-the-market", this implementation also shows a nice improvement.
Benchmarking Result (A fixture written with `mitata`)
115.65 ns/iter112.17 ns116.77 ns126.67 ns188.02 ns129.99 ns/iter15.72 ns16.84 ns2.96 µs3.13 µs350.84 ns/iter193.97 ns200.49 ns3.23 µs3.25 µs99.92 ns/iter94.84 ns100.61 ns110.28 ns180.62 ns295.60 ns/iter97.50 ns101.80 ns6.57 µs6.82 µs693.57 ns/iter250.81 ns260.74 ns6.86 µs6.89 µs110.30 ns/iter106.86 ns111.46 ns118.16 ns142.25 ns421.55 ns/iter140.63 ns151.12 ns10.22 µs10.38 µs959.55 ns/iter287.52 ns294.57 ns10.26 µs10.36 µs105.53 ns/iter102.23 ns106.72 ns113.43 ns124.67 ns364.62 ns/iter156.70 ns169.64 ns10.70 µs12.95 µs1.22 µs/iter261.57 ns341.41 ns14.94 µs15.42 µs130.76 ns/iter124.11 ns130.69 ns164.40 ns195.94 ns488.59 ns/iter109.83 ns115.52 ns13.61 µs14.94 µs1.49 µs/iter314.71 ns325.68 ns15.31 µs15.40 µs236.00 ns/iter224.22 ns238.94 ns254.77 ns284.88 ns534.01 ns/iter74.33 ns87.20 ns15.56 µs16.40 µs1.63 µs/iter324.28 ns336.46 ns16.45 µs16.55 µs295.56 ns/iter288.08 ns297.49 ns314.01 ns342.31 ns571.17 ns/iter98.33 ns104.45 ns16.58 µs17.09 µs1.34 µs/iter276.71 ns301.73 ns15.57 µs15.69 µs135.89 ns/iter130.60 ns136.42 ns168.18 ns189.51 ns609.29 ns/iter88.90 ns102.36 ns16.24 µs17.62 µs2.11 µs/iter426.18 ns437.44 ns19.55 µs19.98 µs| • match: extglob + braces "foo/+(bar|baz)/**/*.{html,js}" | avg | min | p75 | p99 | max |
| ----------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- |
| ours (path.matchesGlob) |
436.93 ns/iter|423.99 ns|439.49 ns|464.45 ns|481.09 ns|| picomatch |
603.44 ns/iter|85.91 ns|89.78 ns|16.76 µs|17.67 µs|| minimatch |
1.80 µs/iter|349.27 ns|365.06 ns|20.80 µs|21.20 µs|305.51 ns/iter292.63 ns310.04 ns324.35 ns335.83 ns552.86 ns/iter54.58 ns59.16 ns18.33 µs19.87 µs848.20 ns/iter113.11 ns117.96 ns19.97 µs20.75 µs96.86 ns/iter93.32 ns96.83 ns123.80 ns132.66 ns773.27 ns/iter174.68 ns182.25 ns22.29 µs24.21 µs699.20 ns/iter111.01 ns117.18 ns23.31 µs23.80 µs108.49 ns/iter105.86 ns109.03 ns118.33 ns123.97 ns703.31 ns/iter62.55 ns69.33 ns24.25 µs25.31 µs1.82 µs/iter315.17 ns340.18 ns25.59 µs25.63 µs46.75 µs/iter43.92 µs46.79 µs65.75 µs147.54 µs522.44 µs/iter480.70 µs531.32 µs547.48 µs600.84 µs683.26 µs/iter101.25 µs103.83 µs130.08 µs126.54 ms53.18 µs/iter52.80 µs53.25 µs53.56 µs53.59 µs673.80 µs/iter624.79 µs692.34 µs719.43 µs733.56 µs765.62 µs/iter110.83 µs114.29 µs188.17 µs159.80 ms98.90 µs/iter91.33 µs100.54 µs130.75 µs204.67 µs794.39 µs/iter766.46 µs801.54 µs827.51 µs828.21 µs2.22 ms/iter174.75 µs231.50 µs681.04 µs165.86 ms| • filter 473 paths: "**/*.@(md|json)" | avg | min | p75 | p99 | max |
| ----------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- |
| ours (path.matchesGlob) |
211.23 µs/iter|197.08 µs|209.67 µs|266.04 µs|371.67 µs|| picomatch |
521.65 µs/iter|483.29 µs|523.77 µs|563.30 µs|634.47 µs|| minimatch |
792.63 µs/iter|117.17 µs|120.25 µs|143.08 µs|180.25 ms|3.61 µs/iter3.50 µs3.61 µs3.65 µs3.67 µs33.06 µs/iter2.46 µs7.54 µs32.38 µs149.31 ms12.69 µs/iter5.21 µs14.42 µs38.75 µs137.63 µs1.73 µs/iter1.65 µs1.74 µs1.83 µs1.83 µs4.76 ms/iter4.74 ms4.76 ms4.81 ms4.84 ms4.35 ms/iter4.24 ms4.32 ms4.70 ms4.81 ms| • stress: repeated extglob "+(a|b)+(a|b)+(a|b)*c" | avg | min | p75 | p99 | max |
| ----------------------- | ---------------- | ----------- | ----------- | ----------- | ----------- |
| ours (path.matchesGlob) |
4.69 µs/iter|4.55 µs|4.74 µs|4.87 µs|4.97 µs|| picomatch |
25.05 µs/iter|15.83 µs|16.57 µs|16.82 µs|122.37 µs|| minimatch |
24.64 µs/iter|14.84 µs|15.56 µs|15.92 µs|125.47 µs|138.40 ns/iter133.54 ns138.21 ns163.71 ns193.29 ns225.15 ns/iter209.12 ns232.94 ns244.57 ns246.80 ns3.56 µs/iter500.14 ns519.71 ns522.99 ns43.14 µs489.51 ns/iter470.98 ns497.42 ns517.31 ns533.83 ns520.94 ns/iter96.63 ns110.26 ns505.96 ns38.76 µs962.92 ns/iter205.40 ns215.36 ns317.59 ns36.19 µs1.67 ms/iter1.61 ms1.67 ms2.12 ms2.39 ms2.89 ms/iter2.56 ms2.99 ms3.44 ms3.81 ms1.78 ms/iter1.69 ms1.79 ms2.03 ms2.74 ms1.67 ms/iter1.61 ms1.66 ms1.97 ms2.07 ms2.27 ms/iter2.15 ms2.24 ms2.83 ms2.99 ms1.75 ms/iter1.67 ms1.76 ms2.14 ms2.34 ms79.67 µs/iter77.00 µs79.42 µs101.21 µs266.54 µs503.25 µs/iter118.38 µs136.38 µs228.04 µs163.89 ms84.56 µs/iter76.46 µs87.21 µs119.38 µs167.63 µs6.19 ms/iter6.10 ms6.23 ms6.33 ms6.35 ms98.22 ms/iter12.69 ms196.59 ms199.43 ms478.81 ms5.53 ms/iter4.95 ms5.78 ms6.02 ms6.21 msAI-Assisted-By: Claude Fable 5, Claude Opus 5