Commit bb3f9176ca9 for nodejs

commit bb3f9176ca9ae9cc304bd460969046340c14d4a0
Author: Roberto Bianchi <rbianchidev@gmail.com>
Date:   Mon Oct 19 16:53:43 2026 +0200

    fs: reduce glob section allocations

    Store prefix counts in section records to avoid a separate vector
    and its allocations during multi-globstar matching.

    Signed-off-by: Roberto Bianchi <roberto.bianchi@spendesk.com>
    PR-URL: https://github.com/nodejs/node/pull/66716
    Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
    Reviewed-By: James M Snell <jasnell@gmail.com>
    Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>

diff --git a/benchmark/path/matchesGlob-filter.js b/benchmark/path/matchesGlob-filter.js
new file mode 100644
index 00000000000..8439a24fe8a
--- /dev/null
+++ b/benchmark/path/matchesGlob-filter.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const common = require('../common');
+const assert = require('node:assert');
+const { posix, win32 } = require('node:path');
+
+const bench = common.createBenchmark(main, {
+  n: [2e4],
+  platform: ['posix', 'win32'],
+  pattern: ['**/node_modules/**/test/**', '**/src/**'],
+});
+
+function main({ n, platform, pattern }) {
+  const implementation = platform === 'posix' ? posix : win32;
+  const filenames = Array.from({ length: 64 }, (_, index) => {
+    const directory = index % 2 === 0 ? 'node_modules/dependency/test' : 'src';
+    return `workspace/packages/package${index}/${directory}/file${index}.js`
+      .replaceAll('/', implementation.sep);
+  });
+  assert.strictEqual(filenames.filter((filename) => implementation.matchesGlob(filename, pattern)).length, 32);
+  let matches = 0;
+  bench.start();
+  for (let iteration = 0; iteration < n; iteration++) {
+    for (const filename of filenames) matches += implementation.matchesGlob(filename, pattern);
+  }
+  bench.end(n * filenames.length);
+  assert.strictEqual(matches, n * 32);
+}
diff --git a/benchmark/path/matchesGlob-sections.js b/benchmark/path/matchesGlob-sections.js
new file mode 100644
index 00000000000..55f5d4de6ad
--- /dev/null
+++ b/benchmark/path/matchesGlob-sections.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const common = require('../common');
+const assert = require('node:assert');
+const { posix, win32 } = require('node:path');
+
+const bench = common.createBenchmark(main, {
+  n: [1e5],
+  platform: ['posix', 'win32'],
+  count: [1, 2, 4, 10, 16],
+  result: ['hit', 'miss'],
+});
+
+function main({ n, platform, count, result }) {
+  const implementation = platform === 'posix' ? posix : win32;
+  const names = Array.from({ length: count - 1 }, (_, index) => `part${index}`);
+  const pattern = ['**', ...names.flatMap((name) => [name, '**']), 'file.js'].join('/');
+  const parts = ['root', ...names.flatMap((name) => [name, 'dir']), 'file.js'];
+  if (result === 'miss') {
+    if (names.length) parts[parts.length - 3] = 'absent';
+    else parts[parts.length - 1] = 'file.txt';
+  }
+  const filename = parts.join(implementation.sep);
+  const expected = result === 'hit';
+  assert.strictEqual(implementation.matchesGlob(filename, pattern), expected);
+  let actual;
+  bench.start();
+  for (let index = 0; index < n; index++) actual = implementation.matchesGlob(filename, pattern);
+  bench.end(n);
+  assert.strictEqual(actual, expected);
+}
diff --git a/src/glob/glob_matcher.cc b/src/glob/glob_matcher.cc
index 37da737dbe4..e0cca5cf43e 100644
--- a/src/glob/glob_matcher.cc
+++ b/src/glob/glob_matcher.cc
@@ -584,6 +584,7 @@ class PathMatcher {
   struct Section {
     size_t begin, end;  // pattern part indices
     ptrdiff_t after;    // last possible file index this section can start at
+    size_t non_gs;
   };

   Tri MatchGlobstar(Parts file,
@@ -660,13 +661,11 @@ class PathMatcher {
     // split body into globstar-delimited sections with their last possible
     // start positions
     std::vector<Section> sections;
-    sections.push_back({body_begin, body_begin, 0});
-    std::vector<size_t> non_gs_sums{0};
+    sections.push_back({body_begin, body_begin, 0, 0});
     size_t non_gs = 0;
     for (size_t i = body_begin; i < body_end; i++) {
       if (pattern[i].kind == PartMatcher::Kind::kGlobstar) {
-        non_gs_sums.push_back(non_gs);
-        sections.push_back({i + 1, i + 1, 0});
+        sections.push_back({i + 1, i + 1, 0, non_gs});
       } else {
         sections.back().end = i + 1;
         non_gs++;
@@ -677,7 +676,7 @@ class PathMatcher {
     {
       size_t i = sections.size() - 1;
       for (Section& s : sections) {
-        s.after = file_length - (static_cast<ptrdiff_t>(non_gs_sums[i--]) +
+        s.after = file_length - (static_cast<ptrdiff_t>(sections[i--].non_gs) +
                                  static_cast<ptrdiff_t>(s.end - s.begin));
       }
     }
diff --git a/test/parallel/test-path-glob-sections.js b/test/parallel/test-path-glob-sections.js
new file mode 100644
index 00000000000..7bc26f9edc5
--- /dev/null
+++ b/test/parallel/test-path-glob-sections.js
@@ -0,0 +1,25 @@
+'use strict';
+
+require('../common');
+const assert = require('node:assert');
+const { posix, win32 } = require('node:path');
+
+for (const implementation of [posix, win32]) {
+  for (const count of [1, 2, 4, 8, 9, 10, 16]) {
+    for (const prefix of ['part', '\u00e9tage', '\u4e2d']) {
+      const names = Array.from({ length: count - 1 }, (_, index) => `${prefix}${index}`);
+      const pattern = ['**', ...names.flatMap((name) => [name, '**']), 'file.js'].join('/');
+      const parts = ['root', ...names.flatMap((name) => [name, 'dir']), 'file.js'];
+      assert.strictEqual(implementation.matchesGlob(parts.join(implementation.sep), pattern), true);
+      if (names.length) {
+        parts[parts.length - 3] = 'absent';
+      } else {
+        parts[parts.length - 1] = 'file.txt';
+      }
+      assert.strictEqual(implementation.matchesGlob(parts.join(implementation.sep), pattern), false);
+    }
+  }
+  assert.strictEqual(implementation.matchesGlob('root/.hidden/src/lib/file.js', '**/src/**/file.js'), false);
+  assert.strictEqual(implementation.matchesGlob('root/src/./lib/file.js', '**/src/**/file.js'), true);
+  assert.strictEqual(implementation.matchesGlob('root/src/lib/file.js/', '**/src/**/file.js'), true);
+}