Skip to content

Commit

Permalink
Implement recursive option in fs.readdir (oven-sh#7296)
Browse files Browse the repository at this point in the history
* Implement `fs.readdir(path, {recursive: true})` and `fs.readdirSync(path, {recursive: true})`

* Update node_fs.zig

* FIx memory leak in error code

* Add fail test

* Update readdir.mjs

* Update bun.zig

* Update readdir.mjs

---------

Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
  • Loading branch information
2 people authored and ryoppippi committed Feb 1, 2024
1 parent 1d0d024 commit a25749c
Show file tree
Hide file tree
Showing 6 changed files with 857 additions and 58 deletions.
49 changes: 43 additions & 6 deletions bench/snippets/readdir.mjs
Original file line number Diff line number Diff line change
@@ -1,13 +1,50 @@
import { readdirSync } from "fs";
import { readdirSync, readdir as readdirCb } from "fs";
import { readdir } from "fs/promises";
import { bench, run } from "./runner.mjs";
import { argv } from "process";
import { fileURLToPath } from "url";
import { relative, resolve } from "path";
import { createHash } from "crypto";

const dir = argv.length > 2 ? argv[2] : "/tmp";
let dir = resolve(argv.length > 2 ? argv[2] : fileURLToPath(new URL("../../node_modules", import.meta.url)));
if (dir.includes(process.cwd())) {
dir = relative(process.cwd(), dir);
}

const count = readdirSync(dir).length;
bench(`readdir("${dir}")`, () => {
readdirSync(dir, { withFileTypes: true });
const result = await readdir(dir, { recursive: true });
const count = result.length;
const syncCount = readdirSync(dir, { recursive: true }).length;

const hash = createHash("sha256").update(result.sort().join("\n")).digest("hex");

bench(`await readdir("${dir}", {recursive: true})`, async () => {
await readdir(dir, { recursive: true });
});

bench(`await readdir("${dir}", {recursive: true}) x 10`, async () => {
const promises = [
readdir(dir, { recursive: true }),
readdir(dir, { recursive: true }),
readdir(dir, { recursive: true }),
readdir(dir, { recursive: true }),
readdir(dir, { recursive: true }),
readdir(dir, { recursive: true }),
readdir(dir, { recursive: true }),
readdir(dir, { recursive: true }),
readdir(dir, { recursive: true }),
readdir(dir, { recursive: true }),
readdir(dir, { recursive: true }),
];
await Promise.all(promises);
});

bench(`await readdir("${dir}", {recursive: false})`, async () => {
await readdir(dir, { recursive: false });
});

await run();
console.log("\n\nFor", count, "files/dirs in", dir);
console.log("\n", count, "files/dirs in", dir, "\n", "SHA256:", hash, "\n");

if (count !== syncCount) {
throw new Error(`Mismatched file counts: ${count} async !== ${syncCount} sync`);
}
6 changes: 6 additions & 0 deletions src/bun.js/event_loop.zig
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ const Write = JSC.Node.Async.write;
const Truncate = JSC.Node.Async.truncate;
const FTruncate = JSC.Node.Async.ftruncate;
const Readdir = JSC.Node.Async.readdir;
const ReaddirRecursive = JSC.Node.Async.readdir_recursive;
const Readv = JSC.Node.Async.readv;
const Writev = JSC.Node.Async.writev;
const Close = JSC.Node.Async.close;
Expand Down Expand Up @@ -375,6 +376,7 @@ pub const Task = TaggedPointerUnion(.{
Truncate,
FTruncate,
Readdir,
ReaddirRecursive,
Close,
Rm,
Rmdir,
Expand Down Expand Up @@ -821,6 +823,10 @@ pub const EventLoop = struct {
var any: *Readdir = task.get(Readdir).?;
any.runFromJSThread();
},
@field(Task.Tag, typeBaseName(@typeName(ReaddirRecursive))) => {
var any: *ReaddirRecursive = task.get(ReaddirRecursive).?;
any.runFromJSThread();
},
@field(Task.Tag, typeBaseName(@typeName(Close))) => {
var any: *Close = task.get(Close).?;
any.runFromJSThread();
Expand Down
Loading

0 comments on commit a25749c

Please sign in to comment.