Skip to content

Commit 8a7bf86

Browse files
CopilotKSXGitHub
andcommitted
Add competing benchmark workflow for pdu vs dust vs dua
Co-authored-by: KSXGitHub <11488886+KSXGitHub@users.noreply.github.com>
1 parent 89b213d commit 8a7bf86

2 files changed

Lines changed: 185 additions & 0 deletions

File tree

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
name: Competing Benchmark (pdu vs dust vs dua)
2+
3+
on:
4+
workflow_dispatch: {}
5+
6+
jobs:
7+
competing_benchmark:
8+
name: Benchmark
9+
10+
# benchmark needs to run in a quiet environment, without other processes to produce noise.
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v6
15+
16+
- name: Cache (rust)
17+
uses: actions/cache@v5
18+
timeout-minutes: 2
19+
continue-on-error: true
20+
with:
21+
path: |
22+
~/.cargo
23+
target
24+
key: ${{ github.job }}-Linux-${{ hashFiles('rust-toolchain') }}-${{ hashFiles('**/Cargo.lock') }}
25+
restore-keys: |
26+
${{ github.job }}-Linux-${{ hashFiles('rust-toolchain') }}-${{ hashFiles('**/Cargo.lock') }}
27+
${{ github.job }}-Linux-${{ hashFiles('rust-toolchain') }}-
28+
29+
- name: Install Rust
30+
shell: bash
31+
run: |
32+
installer=$(mktemp -d)/install-rustup
33+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > $installer
34+
bash $installer --default-toolchain $(cat rust-toolchain) -y
35+
36+
- name: Build pdu (master)
37+
run: |
38+
cargo build --release
39+
echo "$(pwd)/target/release" >> "$GITHUB_PATH"
40+
41+
- name: Install dust (latest)
42+
run: |
43+
DUST_VERSION=$(curl -sf https://api.github.com/repos/bootandy/dust/releases/latest | jq -r '.tag_name' | sed 's/^v//')
44+
echo "Installing dust ${DUST_VERSION}"
45+
mkdir -p DUST.tmp
46+
archive_name="dust-v${DUST_VERSION}-x86_64-unknown-linux-gnu"
47+
curl -L "https://github.com/bootandy/dust/releases/download/v${DUST_VERSION}/${archive_name}.tar.gz" > tmp.dust.tar.gz
48+
tar xf tmp.dust.tar.gz --directory=DUST.tmp
49+
chmod +x "DUST.tmp/${archive_name}/dust"
50+
echo "$(pwd)/DUST.tmp/${archive_name}" >> "$GITHUB_PATH"
51+
52+
- name: Install dua (latest)
53+
run: |
54+
DUA_VERSION=$(curl -sf https://api.github.com/repos/Byron/dua-cli/releases/latest | jq -r '.tag_name' | sed 's/^v//')
55+
echo "Installing dua ${DUA_VERSION}"
56+
mkdir -p DUA.tmp
57+
archive_name="dua-v${DUA_VERSION}-x86_64-unknown-linux-musl"
58+
curl -L "https://github.com/Byron/dua-cli/releases/download/v${DUA_VERSION}/${archive_name}.tar.gz" > tmp.dua.tar.gz
59+
tar xf tmp.dua.tar.gz --directory=DUA.tmp
60+
chmod +x "DUA.tmp/${archive_name}/dua"
61+
echo "$(pwd)/DUA.tmp/${archive_name}" >> "$GITHUB_PATH"
62+
63+
- name: Install hyperfine
64+
env:
65+
REPO: https://github.com/sharkdp/hyperfine
66+
VERSION: '1.19.0'
67+
run: |
68+
mkdir -p HYPERFINE.tmp
69+
archive_name="hyperfine-v${VERSION}-x86_64-unknown-linux-gnu"
70+
curl -L "${REPO}/releases/download/v${VERSION}/${archive_name}.tar.gz" > tmp.hyperfine.tar.gz
71+
tar xf tmp.hyperfine.tar.gz --directory=HYPERFINE.tmp
72+
chmod +x "HYPERFINE.tmp/${archive_name}/hyperfine"
73+
echo "$(pwd)/HYPERFINE.tmp/${archive_name}" >> "$GITHUB_PATH"
74+
75+
- name: Inspect command locations
76+
run: |
77+
which pdu
78+
which dust
79+
which dua
80+
which hyperfine
81+
82+
- name: Inspect versions
83+
run: |
84+
pdu --version
85+
dust --version
86+
dua --version
87+
hyperfine --version
88+
89+
- name: Prepare directory to be measured
90+
run: |
91+
mkdir -p tmp.sample
92+
curl -L https://github.com/torvalds/linux/archive/refs/tags/v5.12.zip > tmp.sample.zip
93+
unzip tmp.sample.zip -d tmp.sample
94+
./ci/make-tree-with-hardlinks.sh tmp.sample
95+
96+
- name: Install Node.js
97+
uses: actions/setup-node@v6
98+
with:
99+
node-version: '16.1.0'
100+
101+
- name: Cache (pnpm)
102+
uses: actions/cache@v5
103+
timeout-minutes: 2
104+
continue-on-error: true
105+
with:
106+
path: ~/.pnpm-store/v3
107+
key: pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
108+
restore-keys: |
109+
pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
110+
pnpm-
111+
112+
- name: Setup pnpm
113+
uses: pnpm/action-setup@v4.2.0
114+
with:
115+
version: '7.9.0'
116+
run_install: 'true'
117+
118+
- name: Compile TypeScript
119+
run: |
120+
cd ci/github-actions
121+
pnpm exec tsc
122+
123+
- name: Compare benchmark of pdu against dust and dua
124+
run: node ci/github-actions/competing-benchmark-pdu-dust-dua.js
125+
126+
- name: Create chart for benchmark reports
127+
run: node ci/github-actions/illustrate-benchmark-reports.js
128+
129+
- name: Create archive of benchmark reports
130+
run: tar czf tmp.benchmark-reports.tar.gz tmp.benchmark-report.*
131+
132+
- name: Upload benchmark reports
133+
uses: actions/upload-artifact@v7
134+
with:
135+
name: benchmark-reports
136+
path: tmp.benchmark-reports.tar.gz
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import console from 'console'
2+
import exec from 'exec-inline'
3+
import shCmd from 'shell-escape'
4+
import * as reportFiles from './benchmark/report-files'
5+
import STRICT_BASH from './benchmark/strict-bash'
6+
7+
const PDU_DUST_DUA_MATRIX = [
8+
{
9+
id: 'apparent-size',
10+
pduCliArgs: ['--quantity=apparent-size'],
11+
competitors: [
12+
['dust', '--no-progress', '--apparent-size'],
13+
['dua', '--count-hard-links', '--apparent-size'],
14+
],
15+
},
16+
{
17+
id: 'block-size',
18+
pduCliArgs: ['--quantity=block-size'],
19+
competitors: [
20+
['dust', '--no-progress'],
21+
['dua', '--count-hard-links'],
22+
],
23+
},
24+
{
25+
id: 'deduplicate-hardlinks',
26+
pduCliArgs: ['--deduplicate-hardlinks'],
27+
competitors: [
28+
['dust', '--no-progress'],
29+
['dua'],
30+
],
31+
},
32+
] as const
33+
34+
const errexit = (param: { readonly status: number | null }) => param.status !== 0
35+
36+
for (const { id, pduCliArgs, competitors } of PDU_DUST_DUA_MATRIX) {
37+
const commands = [
38+
`pdu ${pduCliArgs.join(' ')} tmp.sample`,
39+
...competitors.map(argv => `${argv.join(' ')} tmp.sample` as const),
40+
] as const
41+
console.error({ id, commands })
42+
const reportName = `competing.${id}` as const
43+
const exportReports = reportFiles.hyperfineArgs(reportName)
44+
const commandLog = reportFiles.getFileName(reportName, 'log')
45+
const hyperfineCommand = shCmd(['hyperfine', '--warmup=1', ...exportReports, ...commands])
46+
const shellCommand = `${hyperfineCommand} 2>&1 | tee ${commandLog}`
47+
exec(...STRICT_BASH, '-c', shellCommand).exit(errexit)
48+
console.error()
49+
}

0 commit comments

Comments
 (0)