Skip to Content
GuideExecution Model

Execution Model

Vooya FS optimizes the amount of useful work performed per JavaScript-to-native boundary crossing.

Why single calls often do not win

For a tiny operation, Node already reaches an optimized native filesystem API. A Vooya FS call adds Node-API argument conversion, task scheduling, and result conversion. Rust cannot remove those fixed costs, so node:fs often wins.

Where native batching changes the shape

A recursive JavaScript implementation commonly repeats this sequence thousands of times: await a directory read, create JS objects, schedule more calls, perform metadata calls, and filter in JavaScript. Vooya FS can keep that loop inside Rust:

JS: one request ↓ Rust: parallel walk → pattern filter → metadata → deterministic sort ↓ JS: one result array

The gain is not “Rust syscall versus Node syscall.” It comes from fewer crossings, less promise orchestration, fused passes, and bounded native parallelism.

Concurrency semantics

concurrency: 1 selects a serial path where supported. A value greater than one sets the per-operation worker count on native paths. Defaults differ by API; see the concurrency table. Node compatibility routes validate this extension but use Node’s own scheduling. Higher values are not guaranteed to be faster, especially on SSDs or small trees. Measure the representative tree and workload.

Native versus WASI

ConcernNode-API native addonNode WASI/WebAssembly
Filesystem accessDirect OS APIsCapability/preopen mediated
Parallel traversalNative threads and RayonDepends on WASM threads/runtime setup
Unix permission/owner semanticsDirectly availablePartial or host-specific
DeploymentPlatform binary packagesMore portable module artifact
Likely advantage hereThroughput and fidelityIsolation and portability

WASM can outperform JavaScript for compute-heavy loops with compact data exchange. It does not remove filesystem syscalls or the host boundary, and copying/marshalling can dominate small calls. For this repository’s current workload, native Node-API is the performance and semantic baseline; WASI is a separate future product choice.

Reproducible Node 24 probe

The repository includes experiments/node-wasi, which instantiates a Rust wasm32-wasip1 module once and gives it a /data preopen. On Apple M4 Pro / Node 24.20.0, a 2,728-file / 341-directory traversal produced these 10-sample means:

PathMean
Node recursive readdirSync + lstatSync19.76 ms
Native Node-API scanSync9.86 ms
WASI Preview 1 count-only traversal15.96 ms

This setup favors WASI: the module returns one integer and performs no JS result conversion or sorting, while native scanSync returns full sorted metadata. Even under that condition, the native path was about 1.62x faster. Module compilation and instantiation were excluded from all samples.

Last updated on