Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
425d393
feat: fio benchmark infrastructure mirroring mountpoint-s3
XciD Mar 8, 2026
8461b6e
feat: add --no-disk-cache flag to disable xorb chunk cache
XciD Mar 8, 2026
f1373cc
feat: add mixed read/write fio benchmark jobs
XciD Mar 8, 2026
c6405d5
refactor: replace old bench tests with posix_test.sh script
XciD Mar 8, 2026
a68ab30
refactor: remove posix_test.sh, add NFS pjdfstest
XciD Mar 8, 2026
9f5a76c
chore: remove outdated BENCHMARKING.md
XciD Mar 8, 2026
b7820af
feat: unified bench script with all categories and mount modes
XciD Mar 8, 2026
0441e54
fix: update CI workflows for unified fs_bench.sh
XciD Mar 8, 2026
07c32d5
perf: populate read benchmarks with real CAS data
XciD Mar 8, 2026
a6d5ac0
perf: add FOPEN_DIRECT_IO to bypass kernel page cache
XciD Mar 9, 2026
7b97a88
chore: use m5dn-24xlarge runner, increase fio timeout, skip populate …
XciD Mar 12, 2026
89530e9
fix: handle stale pjdfstest directory on self-hosted runners
XciD Mar 12, 2026
84ff7ae
fix: add file lock to prevent pjdfstest build race between FUSE and N…
XciD Mar 12, 2026
c93a257
feat: switch CI to prod, add workflow_dispatch for full 100G benchmarks
XciD Mar 12, 2026
61a5933
chore: remove redundant bench job from CI (handled by bench_perf.yml)
XciD Mar 12, 2026
571ed99
refactor: remove label trigger, add job summary for throughput and la…
XciD Mar 12, 2026
75dcf8a
chore: also run performance benchmarks on pull requests
XciD Mar 12, 2026
67ae1a5
feat: run perf benchmarks on PRs, post throughput and latency as PR c…
XciD Mar 12, 2026
cea0dbe
fix: read token_file during initial auth in from_source
XciD Mar 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 207 additions & 0 deletions .github/workflows/bench_perf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
name: Performance Benchmarks

# Mirrors the mountpoint-s3 benchmark CI approach.
# mountpoint-s3 runs on m5dn.24xlarge (100 Gbps, NVMe local cache).
# For comparable results, run on a high-network instance of equivalent class.
#
# Triggers:
# - Every push to main -> publishes results to gh-pages (historical charts)
# - Manual dispatch -> full 100G benchmarks with pre-populated bucket

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
inputs:
bucket:
description: "Pre-populated bucket for big file benchmarks (e.g. XciD/hf-bench)"
required: true
default: "XciD/hf-bench"
job_filter:
description: "Job name filter (empty = all jobs including 100G)"
required: false
default: ""
iterations:
description: "Number of iterations per job"
required: false
default: "3"
categories:
description: "Comma-separated benchmark categories"
required: false
default: "read"

jobs:
bench:
name: Throughput
runs-on:
group: hf-mount-ci-m5dn-24xlarge
timeout-minutes: 120
permissions:
contents: write
pull-requests: write
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y fuse3 libfuse3-dev fio jq
echo 'user_allow_other' | sudo tee -a /etc/fuse.conf

- name: Build
run: cargo build --release

- name: Run throughput benchmarks
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
# Full benchmarks with pre-populated bucket
HF_BENCH_BUCKET="${{ inputs.bucket }}" \
HF_JOB_NAME_FILTER="${{ inputs.job_filter }}" \
iterations=${{ inputs.iterations }} \
HF_CATEGORIES="${{ inputs.categories }}" \
./scripts/fs_bench.sh 2>&1 | tee bench.log
else
# Push to main: small files only to keep runtime reasonable
HF_JOB_NAME_FILTER=small iterations=3 \
HF_CATEGORIES=read,write,mix \
./scripts/fs_bench.sh 2>&1 | tee bench.log
fi

- name: Publish throughput results to gh-pages
uses: benchmark-action/github-action-benchmark@v1
with:
name: Throughput (MiB/s)
tool: customBiggerIsBetter
output-file-path: results/fuse/output.json
benchmark-data-dir-path: dev/bench
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: ${{ github.event_name == 'push' }}
comment-on-alert: true
alert-threshold: 150%
fail-on-alert: false
summary-always: true

- name: Post results summary
if: always()
run: |
echo "## Throughput Benchmark Results" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "| Job | Throughput |" >> "$GITHUB_STEP_SUMMARY"
echo "|-----|-----------|" >> "$GITHUB_STEP_SUMMARY"
jq -r '.[] | "| \(.name) | \(.value | round) \(.unit) |"' results/fuse/output.json >> "$GITHUB_STEP_SUMMARY" 2>/dev/null || echo "| (no results) | |" >> "$GITHUB_STEP_SUMMARY"

- name: Post PR comment
if: github.event_name == 'pull_request'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
RESULTS=$(jq -r '.[] | "| \(.name) | \(.value | round) \(.unit) |"' results/fuse/output.json)
PR="${{ github.event.pull_request.number }}"
MARKER="<!-- perf-throughput-results -->"
BODY=$(cat <<EOFBODY
${MARKER}
## Throughput Benchmark Results

| Job | Throughput |
|-----|-----------|
${RESULTS}
EOFBODY
)

COMMENT_ID=$(gh api "repos/${{ github.repository }}/issues/${PR}/comments" \
--jq ".[] | select(.body | startswith(\"${MARKER}\")) | .id" | head -1)
if [[ -n "${COMMENT_ID}" ]]; then
gh api "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}" \
-X PATCH -f body="${BODY}"
else
gh pr comment "${PR}" --body "${BODY}"
fi

latency-bench:
name: Latency (TTFB)
runs-on:
group: hf-mount-ci-m5dn-24xlarge
timeout-minutes: 30
permissions:
contents: write
pull-requests: write
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y fuse3 libfuse3-dev fio jq
echo 'user_allow_other' | sudo tee -a /etc/fuse.conf

- name: Build
run: cargo build --release

- name: Run latency benchmarks
run: |
HF_CATEGORIES=read_latency,write_latency \
./scripts/fs_bench.sh 2>&1 | tee latency.log

- name: Publish latency results to gh-pages
uses: benchmark-action/github-action-benchmark@v1
with:
name: Latency - TTFB (ms)
tool: customSmallerIsBetter
output-file-path: results/fuse/output.json
benchmark-data-dir-path: dev/latency_bench
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: ${{ github.event_name == 'push' }}
comment-on-alert: true
alert-threshold: 150%
fail-on-alert: false
summary-always: true

- name: Post results summary
if: always()
run: |
echo "## Latency Benchmark Results (TTFB)" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "| Job | Latency |" >> "$GITHUB_STEP_SUMMARY"
echo "|-----|---------|" >> "$GITHUB_STEP_SUMMARY"
jq -r '.[] | "| \(.name) | \(.value | . * 100 | round | . / 100) \(.unit) |"' results/fuse/output.json >> "$GITHUB_STEP_SUMMARY" 2>/dev/null || echo "| (no results) | |" >> "$GITHUB_STEP_SUMMARY"

- name: Post PR comment
if: github.event_name == 'pull_request'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
RESULTS=$(jq -r '.[] | "| \(.name) | \(.value | . * 100 | round | . / 100) \(.unit) |"' results/fuse/output.json)
PR="${{ github.event.pull_request.number }}"
MARKER="<!-- perf-latency-results -->"
BODY=$(cat <<EOFBODY
${MARKER}
## Latency Benchmark Results (TTFB)

| Job | Latency |
|-----|---------|
${RESULTS}
EOFBODY
)

COMMENT_ID=$(gh api "repos/${{ github.repository }}/issues/${PR}/comments" \
--jq ".[] | select(.body | startswith(\"${MARKER}\")) | .id" | head -1)
if [[ -n "${COMMENT_ID}" ]]; then
gh api "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}" \
-X PATCH -f body="${BODY}"
else
gh pr comment "${PR}" --body "${BODY}"
fi
80 changes: 5 additions & 75 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
lint-test:
name: Lint & Unit Tests
runs-on:
group: hf-mount-ci
group: hf-mount-ci-m5dn-24xlarge
steps:
- uses: actions/checkout@v4

Expand Down Expand Up @@ -52,11 +52,10 @@ jobs:
smoke-test:
name: Smoke Tests (FUSE + NFS)
runs-on:
group: hf-mount-ci
group: hf-mount-ci-m5dn-24xlarge
needs: lint-test
env:
HF_TOKEN: ${{ secrets.HF_TOKEN_HUB_CI }}
HF_ENDPOINT: https://hub-ci.huggingface.co
HF_TOKEN: ${{ secrets.HF_TOKEN }}
steps:
- uses: actions/checkout@v4

Expand Down Expand Up @@ -84,11 +83,10 @@ jobs:
pjdfstest:
name: POSIX Compliance (pjdfstest)
runs-on:
group: hf-mount-ci
group: hf-mount-ci-m5dn-24xlarge
needs: lint-test
env:
HF_TOKEN: ${{ secrets.HF_TOKEN_HUB_CI }}
HF_ENDPOINT: https://hub-ci.huggingface.co
HF_TOKEN: ${{ secrets.HF_TOKEN }}
steps:
- uses: actions/checkout@v4

Expand Down Expand Up @@ -147,71 +145,3 @@ jobs:
echo "Created new comment"
fi

bench:
name: Benchmarks
runs-on:
group: hf-mount-ci
needs: lint-test
env:
HF_TOKEN: ${{ secrets.HF_TOKEN_HUB_CI }}
HF_ENDPOINT: https://hub-ci.huggingface.co
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable

- uses: Swatinem/rust-cache@v2

- name: Install system deps
run: |
sudo apt-get update
sudo apt-get install -y fuse3 libfuse3-dev nfs-common
echo 'user_allow_other' | sudo tee -a /etc/fuse.conf

- name: Build release binaries
run: cargo build --release

- name: Install fio
run: sudo apt-get install -y fio

- name: Run benchmarks
timeout-minutes: 10
run: cargo test --release --test bench --test fio_bench -- --nocapture 2>&1 | tee bench_output.txt

- name: Post benchmark results
if: github.event_name == 'pull_request'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Strip ANSI codes, then extract only ==== delimited blocks
CLEAN=$(sed 's/\x1b\[[0-9;]*m//g' bench_output.txt)
TABLES=$(echo "$CLEAN" | awk '
/^=====*$/ { inside=!inside; print; next }
inside { print }
')
if [ -z "$TABLES" ]; then
echo "No benchmark table found in output"
exit 0
fi

PR="${{ github.event.pull_request.number }}"
MARKER="<!-- bench-results -->"
BODY="${MARKER}
## Benchmark Results

\`\`\`
${TABLES}
\`\`\`"

# Find existing comment with our marker
COMMENT_ID=$(gh api "repos/${{ github.repository }}/issues/${PR}/comments" \
--jq ".[] | select(.body | startswith(\"${MARKER}\")) | .id" | head -1)

if [ -n "$COMMENT_ID" ]; then
gh api "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}" \
-X PATCH -f body="$BODY"
echo "Updated existing comment $COMMENT_ID"
else
gh pr comment "$PR" --body "$BODY"
echo "Created new comment"
fi
18 changes: 18 additions & 0 deletions scripts/fio/create/create_files_100.fio
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[global]
create_on_open=1
nrfiles=10
ioengine=filecreate
fallocate=none
filesize=4k
openfiles=1

[t0]
[t1]
[t2]
[t3]
[t4]
[t5]
[t6]
[t7]
[t8]
[t9]
18 changes: 18 additions & 0 deletions scripts/fio/create/create_files_1000.fio
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[global]
create_on_open=1
nrfiles=100
ioengine=filecreate
fallocate=none
filesize=4k
openfiles=1

[t0]
[t1]
[t2]
[t3]
[t4]
[t5]
[t6]
[t7]
[t8]
[t9]
18 changes: 18 additions & 0 deletions scripts/fio/create/create_files_10000.fio
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[global]
create_on_open=1
nrfiles=1000
ioengine=filecreate
fallocate=none
filesize=4k
openfiles=1

[t0]
[t1]
[t2]
[t3]
[t4]
[t5]
[t6]
[t7]
[t8]
[t9]
18 changes: 18 additions & 0 deletions scripts/fio/create/create_files_100000.fio
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[global]
create_on_open=1
nrfiles=10000
ioengine=filecreate
fallocate=none
filesize=4k
openfiles=1

[t0]
[t1]
[t2]
[t3]
[t4]
[t5]
[t6]
[t7]
[t8]
[t9]
Loading
Loading