Skip to content

Commit aa1a2c6

Browse files
authored
Merge pull request #13 from CoderSerio/feat/carbon-dev
version 0.1.0
2 parents 5bda53e + ab0ff0b commit aa1a2c6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2165
-780
lines changed

.github/workflows/Release.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
# Release:仅维护者触发,构建四平台并发布到 npm
2-
# 触发方式:
3-
# 1. 手动:Actions → Release → Run workflow(使用当前 main 的 package.json version)
4-
# 2. 打 tag:git tag v0.0.3 && git push origin v0.0.3(需先已把 package.json 改为 0.0.3 并 push)
5-
# 仓库需配置 Secrets → NPM_TOKEN(npm 的 Automation token,Publish 权限)
1+
# Release: Maintainer-only; builds four platforms and publishes to npm.
2+
# Main package: @rush-fs/core (see package.json). Platform packages: @rush-fs/rush-fs-darwin-arm64, etc.
3+
# Trigger:
4+
# 1. Manual: Actions → Release → Run workflow (uses current main's package.json version)
5+
# 2. Tag: git tag v0.x.x && git push origin v0.x.x (bump version in package.json / Cargo.toml and push first)
6+
# Required: Secrets → NPM_TOKEN (npm Automation token with Publish permission)
67
name: Release
78
env:
89
DEBUG: napi:*

.yarn/releases/yarn-4.12.0.cjs

Lines changed: 1632 additions & 486 deletions
Large diffs are not rendered by default.

CHANGELOG.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,26 @@ All notable changes to Rush-FS are documented here. The format is based on [Keep
66

77
- (Add new changes here before each release.)
88

9-
## [0.0.5] - (release date TBD)
9+
## [0.1.0] - (release date TBD)
10+
11+
**This release is in beta.** API and behavior may change before 0.1.0 stable. Feedback and issues are welcome.
12+
13+
### Changed
14+
15+
- **Package name:** The main npm package is now **`@rush-fs/core`** (scoped). Install with `pnpm add @rush-fs/core` or `npm i @rush-fs/core`, and import with `import { readdir, readFile, ... } from '@rush-fs/core'`.
16+
- **Migration from `rush-fs`:** If you were using the old unscoped package `rush-fs`, replace it with `@rush-fs/core` in `package.json` and in all imports. The API is unchanged; only the package name and version differ. The old `rush-fs` package may be deprecated on npm in a separate step; prefer `@rush-fs/core` for new installs.
17+
- **glob:** `gitIgnore` option now defaults to **`false`** to align with Node.js `fs.globSync` (no .gitignore filtering by default).
18+
19+
### Fixed
20+
21+
- **glob:** Patterns with a path prefix (e.g. `.dir/**/*.txt` or `src/**/*.ts`) now work when used without an explicit `cwd`; the prefix is used as the search root, matching Node.js behavior.
22+
- **glob:** Recursive pattern `**/*.ext` with `cwd` now correctly recurses into subdirectories.
23+
24+
## [0.0.5]
1025

1126
- Re-publish with `optionalDependencies` correctly injected after `napi prepublish`, so `pnpm i rush-fs` / `npm i rush-fs` auto-installs the platform native binding. No API or behavior changes from 0.0.4.
1227

13-
## [0.0.4] - (release date TBD)
28+
## [0.0.4]
1429

1530
### Fixed
1631

@@ -27,7 +42,8 @@ All notable changes to Rush-FS are documented here. The format is based on [Keep
2742

2843
---
2944

30-
[Unreleased]: https://github.com/CoderSerio/rush-fs/compare/v0.0.5...HEAD
45+
[Unreleased]: https://github.com/CoderSerio/rush-fs/compare/v0.1.0-beta.1...HEAD
46+
[0.1.0]: https://github.com/CoderSerio/rush-fs/compare/v0.0.5...v0.1.0-beta.1
3147
[0.0.5]: https://github.com/CoderSerio/rush-fs/compare/v0.0.4...v0.0.5
3248
[0.0.4]: https://github.com/CoderSerio/rush-fs/compare/v0.0.3...v0.0.4
3349
[0.0.3]: https://github.com/CoderSerio/rush-fs/releases/tag/v0.0.3

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
authors = []
44
edition = "2021"
55
name = "rush_fs"
6-
version = "0.0.5"
6+
version = "0.1.0-beta.1"
77

88
[lib]
99
crate-type = ["cdylib"]

README.md

Lines changed: 41 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66

77
<p align="center">
88
<img src="https://img.shields.io/badge/Written%20in-Rust-orange?style=flat-square" alt="Written in Rust">
9-
<img src="https://img.shields.io/npm/v/rush-fs?style=flat-square" alt="NPM Version">
10-
<img src="https://img.shields.io/npm/l/rush-fs?style=flat-square" alt="License">
9+
<img src="https://img.shields.io/npm/v/@rush-fs/core?style=flat-square" alt="NPM Version">
10+
<img src="https://img.shields.io/npm/l/@rush-fs/core?style=flat-square" alt="License">
11+
<img src="https://img.shields.io/badge/status-beta-orange?style=flat-square" alt="Beta">
1112
<a href="https://github.com/CoderSerio/rush-fs/graphs/contributors"><img src="https://img.shields.io/github/contributors/CoderSerio/rush-fs?style=flat-square" alt="Contributors"></a>
1213
</p>
1314

@@ -20,12 +21,12 @@
2021
## Installation
2122

2223
```bash
23-
npm install rush-fs
24+
npm install @rush-fs/core
2425
# or
25-
pnpm add rush-fs
26+
pnpm add @rush-fs/core
2627
```
2728

28-
When you install `rush-fs`, the package manager should automatically install the **platform-specific native binding** for your OS/arch via `optionalDependencies` (e.g. `@rush-fs/rush-fs-darwin-arm64` on macOS ARM). If the native binding is missing and you see "Cannot find native binding", try:
29+
When you install `@rush-fs/core`, the package manager should automatically install the **platform-specific native binding** for your OS/arch via `optionalDependencies` (e.g. `@rush-fs/rush-fs-darwin-arm64` on macOS ARM). If the native binding is missing and you see "Cannot find native binding", try:
2930

3031
1. Remove `node_modules` and the lockfile (`package-lock.json` or `pnpm-lock.yaml`), then run `pnpm install` (or `npm i`) again.
3132
2. Or install the platform package explicitly:
@@ -34,10 +35,12 @@ When you install `rush-fs`, the package manager should automatically install the
3435
**Windows x64:** `pnpm add @rush-fs/rush-fs-win32-x64-msvc`
3536
**Linux x64 (glibc):** `pnpm add @rush-fs/rush-fs-linux-x64-gnu`
3637

38+
**Migration from `rush-fs`:** The package was renamed to `@rush-fs/core`. See [CHANGELOG.md](./CHANGELOG.md#010) for details.
39+
3740
## Usage
3841

3942
```ts
40-
import { readdir, stat, readFile, writeFile, mkdir, rm } from 'rush-fs'
43+
import { readdir, stat, readFile, writeFile, mkdir, rm } from '@rush-fs/core'
4144

4245
// Read directory
4346
const files = await readdir('./src')
@@ -72,30 +75,30 @@ await rm('./temp', { recursive: true, force: true })
7275

7376
These are the scenarios where Rust's parallelism and zero-copy I/O make a real difference:
7477

75-
| Scenario | Node.js | Rush-FS | Speedup |
76-
| ------------------------------------------------ | --------- | -------- | --------- |
77-
| `readdir` recursive (node_modules, ~30k entries) | 281 ms | 23 ms | **12x** |
78-
| `glob` recursive (`**/*.rs`) | 25 ms | 1.46 ms | **17x** |
79-
| `glob` recursive vs fast-glob | 102 ms | 1.46 ms | **70x** |
80-
| `copyFile` 4 MB | 4.67 ms | 0.09 ms | **50x** |
81-
| `readFile` 4 MB utf8 | 1.86 ms | 0.92 ms | **2x** |
82-
| `readFile` 64 KB utf8 | 42 µs | 18 µs | **2.4x** |
83-
| `rm` 2000 files (4 threads) | 92 ms | 53 ms | **1.75x** |
84-
| `access` R_OK (directory) | 4.18 µs | 1.55 µs | **2.7x** |
85-
| `cp` 500-file flat dir (4 threads) | 86.45 ms | 32.88 ms | **2.6x** |
86-
| `cp` tree dir ~363 nodes (4 threads) | 108.73 ms | 46.88 ms | **2.3x** |
78+
| Scenario | Node.js | Rush-FS | Speedup |
79+
| ----------------------------------------------------------------------- | --------- | -------- | --------- |
80+
| `readdir` recursive (node_modules, ~30k entries) | 281 ms | 23 ms | **12x** |
81+
| `copyFile` 4 MB | 4.67 ms | 0.09 ms | **50x** |
82+
| `readFile` 4 MB utf8 | 1.86 ms | 0.92 ms | **2x** |
83+
| `readFile` 64 KB utf8 | 42 µs | 18 µs | **2.4x** |
84+
| `rm` 2000 files (4 threads) | 92 ms | 53 ms | **1.75x** |
85+
| `access` R_OK (directory) | 4.18 µs | 1.55 µs | **2.7x** |
86+
| `cp` 500-file flat dir (4 threads) | 86.45 ms | 32.88 ms | **2.6x** |
87+
| `cp` tree dir ~363 nodes (4 threads) | 108.73 ms | 46.88 ms | **2.3x** |
88+
| `glob` large tree (`node_modules/**/*.json`, ~30k entries) vs fast-glob | 303 ms | 30 ms | **~10x** |
8789

8890
### On Par with Node.js
8991

90-
Single-file operations have a ~0.3 µs napi bridge overhead, making them roughly equivalent:
92+
Single-file operations have a ~0.3 µs napi bridge overhead. Recursive glob on a **small tree** is on par with node-glob; on **large trees** (e.g. node_modules) Rush-FS wins (see table above).
9193

92-
| Scenario | Node.js | Rush-FS | Ratio |
93-
| -------------------------- | ------- | ------- | ----- |
94-
| `stat` (single file) | 1.45 µs | 1.77 µs | 1.2x |
95-
| `readFile` small (Buffer) | 8.86 µs | 9.46 µs | 1.1x |
96-
| `writeFile` small (string) | 74 µs | 66 µs | 0.9x |
97-
| `writeFile` small (Buffer) | 115 µs | 103 µs | 0.9x |
98-
| `appendFile` | 30 µs | 27 µs | 0.9x |
94+
| Scenario | Node.js | Rush-FS | Ratio |
95+
| ----------------------------------------------------- | ------- | ------- | -------------------------------------- |
96+
| `stat` (single file) | 1.45 µs | 1.77 µs | 1.2x |
97+
| `readFile` small (Buffer) | 8.86 µs | 9.46 µs | 1.1x |
98+
| `writeFile` small (string) | 74 µs | 66 µs | 0.9x |
99+
| `writeFile` small (Buffer) | 115 µs | 103 µs | 0.9x |
100+
| `appendFile` | 30 µs | 27 µs | 0.9x |
101+
| `glob` recursive (`**/*.rs`, small tree) vs node-glob | ~22 ms | ~40 ms | ~1.8x (node-glob faster at this scale) |
99102

100103
### Where Node.js Wins
101104

@@ -122,7 +125,7 @@ Single-file operations (`stat`, `readFile`, `writeFile`, `chmod`, etc.) are atom
122125

123126
### Key Takeaway
124127

125-
**Rush-FS excels at recursive / batch filesystem operations** (readdir, glob, rm, cp) where Rust's parallel walkers deliver 2–70x speedups. For single-file operations it performs on par with Node.js. The napi bridge adds a fixed ~0.3 µs overhead per call, which only matters for sub-microsecond operations like `existsSync`.
128+
**Rush-FS excels at recursive / batch filesystem operations** (readdir, glob, rm, cp) where Rust's parallel walkers deliver significant speedups (e.g. 12x readdir, 50x copyFile). For single-file operations it performs on par with Node.js. The napi bridge adds a fixed ~0.3 µs overhead per call, which only matters for sub-microsecond operations like `existsSync`.
126129

127130
**`cp` benchmark detail** (Apple Silicon, release build):
128131

@@ -136,7 +139,7 @@ Optimal concurrency for `cp` is **4 threads** on Apple Silicon — beyond that,
136139

137140
## How it works
138141

139-
For the original Node.js, it works serially and cost lots of memory to parse os object and string into JS style:
142+
For the original Node.js, **for example** on `readdir`, directory reads run serially in the native layer, and each entry is turned into a JS string on the V8 main thread, which adds GC pressure:
140143

141144
```mermaid
142145
graph TD
@@ -161,29 +164,31 @@ graph TD
161164
E -->|"Return Array"| G["JS Callback/Promise"]
162165
```
163166

164-
But, it's saved with Rust now:
167+
With Rush-FS, **for example** on `readdir`, the hot path stays in Rust: build a `Vec<String>` (or use Rayon for **recursive** readdir), then hand one array to JS. No per-entry V8 allocation during the walk:
165168

166169
```mermaid
167170
graph TD
168171
A["JS: readdir"] -->|"N-API Call"| B("Rust Wrapper")
169-
B -->|"Spawn Thread/Task"| C{"Rust Thread Pool"}
172+
B -->|"Spawn Task"| C{"Rust (or Rayon pool if recursive)"}
170173
171174
subgraph "Rust 'Black Box'"
172-
C -->|"Rayon: Parallel work"| D[OS Kernel]
173-
D -->|"Syscall: getdents"| C
175+
C -->|"Syscall: getdents"| D[OS Kernel]
176+
D -->|"Return file list"| C
174177
C -->|"Store as Rust Vec<String>"| H[Rust Heap]
175-
H -->|"No V8 Interaction yet"| H
178+
H -->|"No V8 yet"| H
176179
end
177180
178181
C -->|"All Done"| I("Convert to JS")
179182
180183
subgraph "N-API Bridge"
181-
I -->|"Batch Create JS Array"| J[V8 Heap]
184+
I -->|"Batch create JS array"| J[V8 Heap]
182185
end
183186
184187
J -->|Return| K["JS Result"]
185188
```
186189

190+
Other sources of speed in Rush-FS: **recursive `readdir`** uses [jwalk](https://github.com/Byron/jwalk) with a Rayon thread pool for parallel directory traversal; **`cp`** and **`rm`** (recursive) can use Rayon for parallel tree walk and I/O; **`glob`** runs with a configurable number of threads. Across APIs, keeping the hot path in Rust and handing a single result (or batched data) to JS avoids repeated V8/GC overhead compared to Node’s C++ binding.
191+
187192
## Status & Roadmap
188193

189194
We are rewriting `fs` APIs one by one.
@@ -192,7 +197,7 @@ We are rewriting `fs` APIs one by one.
192197
>
193198
> - ✅: Fully Supported
194199
> - 🚧: Partially Supported / WIP
195-
> - ✨: New feature from rush-fs
200+
> - ✨: New feature from @rush-fs/core
196201
> - ❌: Not Supported Yet
197202
198203
### `readdir`
@@ -441,7 +446,7 @@ We are rewriting `fs` APIs one by one.
441446
withFileTypes?: boolean; //
442447
exclude?: string[]; //
443448
concurrency?: number; //
444-
gitIgnore?: boolean; //
449+
gitIgnore?: boolean; // default false (align with Node.js fs.globSync)
445450
};
446451
```
447452

0 commit comments

Comments
 (0)