Skip to content

Commit b3959cd

Browse files
authored
test: Fix and update recursive-delete benchmarks (#84875)
PR created with claude code, with some manual review. - Update benchmark scripts to work, given my recent code changes - Include a native nodejs benchmark - Use rimraf's `manual` implementation (tries to use node's native version) - Tried to clean up the code a bit - Use a trap to always clean up - Use getopt and add an `--iterations` option - `set -euo pipefail` to avoid swallowing errors Example output: ``` pnpm bench > bench-recursive-delete@ bench /home/bgw.linux/next.js/bench/recursive-delete > bash run.sh ----------- rimraf (async) 1 62.443657 rimraf (async) 2 52.953482 rimraf (async) 3 52.029235 rimraf (async) 4 50.709822 rimraf (async) 5 54.204893 ----------- rimraf (sync) 1 35.034669 rimraf (sync) 2 35.663417 rimraf (sync) 3 46.360754 rimraf (sync) 4 36.859329 rimraf (sync) 5 34.368796 ----------- recursive delete 1 37.851534 recursive delete 2 35.98904 recursive delete 3 36.620913 recursive delete 4 38.059992 recursive delete 5 43.880346 ----------- nodejs rm (promises) 1 71.301125 nodejs rm (promises) 2 89.78331 nodejs rm (promises) 3 68.073553 nodejs rm (promises) 4 70.787543 nodejs rm (promises) 5 73.727616 ----------- nodejs rm (callback) 1 92.698258 nodejs rm (callback) 2 73.043993 nodejs rm (callback) 3 70.869584 nodejs rm (callback) 4 69.196757 nodejs rm (callback) 5 75.715526 ----------- nodejs rm (sync) 1 41.71002 nodejs rm (sync) 2 41.742395 nodejs rm (sync) 3 38.894571 nodejs rm (sync) 4 41.326271 nodejs rm (sync) 5 48.152122 ```
1 parent 3cd8a23 commit b3959cd

File tree

8 files changed

+135
-86
lines changed

8 files changed

+135
-86
lines changed

bench/recursive-delete/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Recursive Delete Benchmark
2+
3+
```bash
4+
pnpm bench
5+
```
6+
7+
Run `pnpm bench --help` for options.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { rm as rmPromises } from 'fs/promises'
2+
import { rm as rmCallback, rmSync } from 'fs'
3+
import { promisify } from 'util'
4+
5+
const rmCallbackPromise = promisify(rmCallback)
6+
7+
const targetDir = process.argv[2]
8+
const method = process.argv[3] // 'promises', 'callback', or 'sync'
9+
10+
async function test() {
11+
const time = process.hrtime()
12+
13+
if (method === 'promises') {
14+
await rmPromises(targetDir, { recursive: true, force: true })
15+
} else if (method === 'callback') {
16+
await rmCallbackPromise(targetDir, { recursive: true, force: true })
17+
} else if (method === 'sync') {
18+
rmSync(targetDir, { recursive: true, force: true })
19+
}
20+
21+
const hrtime = process.hrtime(time)
22+
const nanoseconds = hrtime[0] * 1e9 + hrtime[1]
23+
const milliseconds = nanoseconds / 1e6
24+
console.log(milliseconds)
25+
}
26+
27+
test()

bench/recursive-delete/output.txt

Whitespace-only changes.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "bench-recursive-delete",
3+
"type": "module",
4+
"scripts": {
5+
"bench": "bash run.sh"
6+
},
7+
"devDependencies": {
8+
"fuzzponent": "workspace:*",
9+
"next": "workspace:*",
10+
"rimraf": "6.0.1"
11+
}
12+
}

bench/recursive-delete/recursive-delete.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { join } from 'path'
2-
import { recursiveDelete } from 'next/dist/lib/recursive-delete'
3-
const resolveDataDir = join(__dirname, `fixtures-${process.argv[2]}`)
1+
import { recursiveDeleteSyncWithAsyncRetries } from 'next/dist/lib/recursive-delete.js'
2+
3+
const targetDir = process.argv[2]
44

55
async function test() {
66
const time = process.hrtime()
7-
await recursiveDelete(resolveDataDir)
7+
await recursiveDeleteSyncWithAsyncRetries(targetDir)
88

99
const hrtime = process.hrtime(time)
1010
const nanoseconds = hrtime[0] * 1e9 + hrtime[1]

bench/recursive-delete/rimraf.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import { join } from 'path'
2-
import { promisify } from 'util'
3-
import rimrafMod from 'rimraf'
1+
import { manual, manualSync } from 'rimraf'
42

5-
const rimraf = promisify(rimrafMod)
6-
const resolveDataDir = join(__dirname, `fixtures-${process.argv[2]}`, '**/*')
3+
const targetDir = process.argv[2]
4+
const method = process.argv[3]
75

86
async function test() {
97
const time = process.hrtime()
10-
await rimraf(resolveDataDir)
8+
9+
if (method === 'sync') {
10+
manualSync(targetDir)
11+
} else {
12+
await manual(targetDir)
13+
}
1114

1215
const hrtime = process.hrtime(time)
1316
const nanoseconds = hrtime[0] * 1e9 + hrtime[1]

bench/recursive-delete/run.sh

Lines changed: 63 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,63 @@
1-
# Uses https://github.com/divmain/fuzzponent
2-
mkdir fixtures-1
3-
cd fixtures-1
4-
fuzzponent -d 2 -s 20 > output.txt
5-
cd ..
6-
echo "rimraf 1"
7-
node rimraf.js 1
8-
9-
mkdir fixtures-2
10-
cd fixtures-2
11-
fuzzponent -d 2 -s 20 > output.txt
12-
cd ..
13-
echo "rimraf 2"
14-
node rimraf.js 2
15-
16-
mkdir fixtures-3
17-
cd fixtures-3
18-
fuzzponent -d 2 -s 20 > output.txt
19-
cd ..
20-
echo "rimraf 3"
21-
node rimraf.js 3
22-
23-
mkdir fixtures-4
24-
cd fixtures-4
25-
fuzzponent -d 2 -s 20 > output.txt
26-
cd ..
27-
echo "rimraf 4"
28-
node rimraf.js 4
29-
30-
mkdir fixtures-5
31-
cd fixtures-5
32-
fuzzponent -d 2 -s 20 > output.txt
33-
cd ..
34-
echo "rimraf 5"
35-
node rimraf.js 5
36-
37-
echo "-----------"
38-
39-
cd fixtures-1
40-
fuzzponent -d 2 -s 20 > output.txt
41-
cd ..
42-
echo "recursive delete 1"
43-
node recursive-delete.js 1
44-
45-
cd fixtures-2
46-
fuzzponent -d 2 -s 20 > output.txt
47-
cd ..
48-
echo "recursive delete 2"
49-
node recursive-delete.js 2
50-
51-
cd fixtures-3
52-
fuzzponent -d 2 -s 20 > output.txt
53-
cd ..
54-
echo "recursive delete 3"
55-
node recursive-delete.js 3
56-
57-
cd fixtures-4
58-
fuzzponent -d 2 -s 20 > output.txt
59-
cd ..
60-
echo "recursive delete 4"
61-
node recursive-delete.js 4
62-
63-
cd fixtures-5
64-
fuzzponent -d 2 -s 20 > output.txt
65-
cd ..
66-
echo "recursive delete 5"
67-
node recursive-delete.js 5
68-
69-
rm -r fixtures-1 fixtures-2 fixtures-3 fixtures-4 fixtures-5
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ITERATIONS=5
5+
6+
show_help() {
7+
echo "Usage: $(basename "$0") [-i|--iterations N] [-h|--help]"
8+
exit "${1:-0}"
9+
}
10+
11+
if ! OPTS=$(getopt -o i:h --long iterations:,help -n "$(basename "$0")" -- "$@"); then
12+
show_help 1
13+
fi
14+
eval set -- "$OPTS"
15+
16+
while true; do
17+
case "$1" in
18+
-i|--iterations)
19+
ITERATIONS="$2"
20+
shift 2
21+
;;
22+
-h|--help)
23+
show_help
24+
;;
25+
*)
26+
break
27+
;;
28+
esac
29+
done
30+
31+
cleanup() {
32+
for i in $(seq 1 "$ITERATIONS"); do
33+
rm -rf "fixtures-$i"
34+
done
35+
}
36+
37+
trap cleanup EXIT
38+
cleanup
39+
40+
run_benchmark() {
41+
local name=$1
42+
local script=$2
43+
shift 2
44+
45+
echo "-----------"
46+
for i in $(seq 1 "$ITERATIONS"); do
47+
local fixture="fixtures-$i"
48+
mkdir "$fixture"
49+
cd "fixtures-$i"
50+
fuzzponent -d 2 -s 20
51+
cd ..
52+
echo "$name $i"
53+
node "$script" "$fixture" "$@"
54+
if [[ -d "$fixture" ]]; then rmdir "$fixture"; fi
55+
done
56+
}
57+
58+
run_benchmark "rimraf (async)" "rimraf.js" "async"
59+
run_benchmark "rimraf (sync)" "rimraf.js" "sync"
60+
run_benchmark "recursive delete" "recursive-delete.js"
61+
run_benchmark "nodejs rm (promises)" "nodejs-rm.js" "promises"
62+
run_benchmark "nodejs rm (callback)" "nodejs-rm.js" "callback"
63+
run_benchmark "nodejs rm (sync)" "nodejs-rm.js" "sync"

pnpm-lock.yaml

Lines changed: 13 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)