@rust-gear/glob
v1.2.1
Published
A fast glob alternative for Node.js powered by Rust.
Downloads
3,203
Maintainers
Readme
@rust-gear/glob
A fast glob alternative for Node.js powered by Rust.
Performance
Measured against fast-glob on a synthetic tree of ~50k files
(Apple Silicon, node bench/bench.mjs, medians):
| pattern (~50k file tree) | globSync | fast-glob sync | fast-glob async |
| :----------------------- | ---------: | ---------------: | ----------------: |
| **/*.js (10k matches) | 26 ms | 74 ms | 41 ms |
| **/*.{js,ts} (18k) | 27 ms | 78 ms | 40 ms |
| **/* + exclude (37.8k) | 30 ms | 78 ms | 41 ms |
| mod1/**/*.rs (400) | 1.4 ms | 3.4 ms | 1.8 ms |
- ~3x faster than the synchronous APIs of
fast-globandglob. The directory walk is parallelized on a Rust thread pool, soglobSyncruns at full speed without blocking on single-threaded I/O. - ~1.6x faster than their async APIs, with ~0.04 ms fixed overhead per call.
Thread pool size
How wide the walk runs is a property of the filesystem, not of the CPU, so it is decided per platform.
On Windows and Linux the pool is every logical CPU the process may use.
NTFS takes a per-directory lock and Linux takes inode->i_rwsem per inode, so
enumerating different directories in parallel does not collide, and the walk
keeps scaling to the full width of the machine:
$ node bench/threads.mjs # Windows 11, 16 logical CPUs, NTFS
threads 1 237.81 ms
threads 8 43.71 ms
threads 16 28.24 ms <- fastest
threads 32 28.43 ms
$ node bench/threads.mjs # Ubuntu, 8 logical CPUs, ext4
threads 1 37.08 ms
threads 4 11.57 ms
threads 8 10.75 ms
threads 16 10.79 msOn macOS it is capped to the machine's fastest core class, read from
hw.perflevel0. APFS serializes enumeration on volume-wide state in the vnode
layer, so wall time bottoms out long before the CPU does — past the knee the
extra threads are queueing in the kernel, not working:
$ node bench/threads.mjs # macOS, Apple Silicon 4P+4E, APFS
threads 1 64.13 ms
threads 4 24.16 ms <- fastest
threads 8 35.16 ms
threads 16 34.76 msThe knee tracks syscall rate rather than core count, so on a Mac with many more performance cores the optimum may sit below their count. On an Intel Mac, where every core is one class, nothing is capped.
Set RUST_GEAR_GLOB_THREADS to override the choice on any platform; run
node bench/threads.mjs to see your own machine's curve. The count is always
clamped to the process's CPU allowance, so a cgroup quota or affinity mask
still wins.
Installation
pnpm add -D @rust-gear/globUsage
import * as rs from "@rust-gear/glob";
const filesAsync = await rs.glob("src/**/*.rs");
const files = rs.globSync("**/*.rs", {
cwd: "src",
exclude: ["**/test/**", "**/target/**"],
});Return paths:
Absolute patterns → absolute paths
Relative patterns → paths relative tocwd
Absolute patterns are resolved inside
cwd. Passcwdwhenever the pattern points outside the current working directory; a pattern that resolves elsewhere throws rather than returning an empty array.
Options
| Option | Type | Default | Description |
| :-------- | :------- | :-------------- | :--------------------------------------------------- |
| cwd | string | process.cwd() | Current working directory for searching |
| exclude | string[] | [] | Glob patterns to exclude |
| dot | boolean | false | Include dot files and directories |
| sort | boolean | false | Return sorted results |
| gitignore | boolean | true | Respect .gitignore files inside git (.git) repos |
Note: Set
gitignore: falsefor results that depend only on the patterns and the filesystem, matching the behavior offast-glob, which never reads.gitignore.
What gitignore reads
The enclosing repository is found by walking up from the directory the search
starts in, and every .gitignore between that repository root and the search
root is applied. The result therefore does not depend on how deep cwd sits,
nor on how much of the path the pattern pins down:
// all three honour the repository's ignore rules, and agree
rs.globSync("**/*.js", { cwd: repo });
rs.globSync("sub/**/*.js", { cwd: repo });
rs.globSync("**/*.js", { cwd: `${repo}/sub` });The one thing not tested against those rules is the search root itself. A
search that starts inside an ignored directory still returns what it finds
there, so pointing cwd at dist or node_modules works as asked. Use
gitignore: false when you want the rules out of the way entirely.
License
Apache-2.0
