Created
July 17, 2026 23:41
-
-
Save teknoraver/ef63104c0a6358a0a1ec9caf7c6ffd24 to your computer and use it in GitHub Desktop.
Tool to benchmark tar with reflnk support
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| # Benchmark tar --reflink extraction against a regular one. | |
| # | |
| # usage: bench.sh <workdir-on-target-fs> <archive>... | |
| # | |
| # Each archive is extracted RUNS times (default 3) in both modes, at | |
| # cold cache when possible, timing tar plus the sync of the extracted | |
| # data; the best run is reported. Contents and extent sharing are | |
| # verified once per archive. | |
| # | |
| # TAR=/path/to/tar overrides the tar binary (default ~/src/tar/src/tar). | |
| set -e | |
| TAR=${TAR:-$HOME/src/tar/src/tar} | |
| RUNS=${RUNS:-3} | |
| dir=${1:?usage: $0 <workdir-on-target-fs> <archive>...} | |
| shift | |
| test $# -gt 0 || { echo "no archives given" >&2; exit 1; } | |
| dir=$(cd "$dir" && pwd) || exit 1 | |
| uname -r | |
| stat -f -c 'fstype=%T bsize=%S' "$dir" | |
| "$TAR" --version | head -1 | |
| echo 3 | sudo -n tee /proc/sys/vm/drop_caches >/dev/null 2>&1 || | |
| echo "note: no sudo, evicting the archive from cache with dd iflag=nocache instead" | |
| echo | |
| # evict the archive ($1) from the page cache; global drop with sudo, | |
| # posix_fadvise(DONTNEED) on the archive alone otherwise, via dd | |
| drop_caches() | |
| { | |
| sync | |
| echo 3 | sudo -n tee /proc/sys/vm/drop_caches >/dev/null 2>&1 || | |
| dd if="$1" iflag=nocache count=0 status=none 2>/dev/null || true | |
| } | |
| now() | |
| { | |
| date +%s.%N | |
| } | |
| # bench_one <archive> <mode: normal|reflink> -> prints best seconds | |
| bench_one() | |
| { | |
| best="" | |
| i=0 | |
| while [ $i -lt "$RUNS" ]; do | |
| rm -rf "$dir/x" | |
| mkdir "$dir/x" | |
| drop_caches "$1" | |
| t0=$(now) | |
| case $2 in | |
| reflink) (cd "$dir/x" && "$TAR" -xf "$1" --reflink) ;; | |
| *) (cd "$dir/x" && "$TAR" -xf "$1") ;; | |
| esac | |
| sync -f "$dir/x" | |
| t1=$(now) | |
| t=$(awk "BEGIN { printf \"%.3f\", $t1 - $t0 }") | |
| best=$(awk "BEGIN { b = \"$best\"; print (b == \"\" || $t < b) ? $t : b }") | |
| i=$((i + 1)) | |
| done | |
| echo "$best" | |
| } | |
| printf '%-28s %10s %10s %9s\n' archive normal reflink speedup | |
| for a in "$@"; do | |
| # downloaded archives are not aligned: extract the content | |
| # once and repack it with --reflink on the target fs | |
| case $a in /*) ;; *) a=$PWD/$a ;; esac | |
| rl=$dir/$(basename "$a" .tar).reflink.tar | |
| if [ ! -f "$rl" ]; then | |
| echo "$(basename "$a"): repacking with --reflink..." >&2 | |
| rm -rf "$dir/unpack" | |
| mkdir "$dir/unpack" | |
| (cd "$dir/unpack" && "$TAR" -xf "$a") | |
| (cd "$dir/unpack" && "$TAR" -cf "$rl" --reflink .) | |
| rm -rf "$dir/unpack" | |
| fi | |
| a=$rl | |
| # correctness: contents must match and extents must be shared | |
| # (skip with VERIFY=0) | |
| if [ "${VERIFY:-1}" != 0 ]; then | |
| echo "$(basename "$a"): verifying contents and sharing..." >&2 | |
| rm -rf "$dir/x" "$dir/ref" | |
| mkdir "$dir/x" "$dir/ref" | |
| (cd "$dir/ref" && "$TAR" -xf "$a") | |
| (cd "$dir/x" && "$TAR" -xf "$a" --reflink) | |
| diff -r "$dir/ref" "$dir/x" > /dev/null || { echo "FAIL: content mismatch for $a" >&2; exit 1; } | |
| sync | |
| f=$(find "$dir/x" -type f -size +4k | head -1) | |
| if [ -n "$f" ] && command -v filefrag > /dev/null; then | |
| filefrag -v "$f" | grep -qi shared || { | |
| echo "FAIL: no shared extents for $a: the reflink" \ | |
| "extraction fell back to a copy, timings would" \ | |
| "be meaningless" >&2 | |
| exit 1 | |
| } | |
| fi | |
| rm -rf "$dir/ref" | |
| fi | |
| echo "$(basename "$a"): benchmarking ($RUNS+$RUNS runs)..." >&2 | |
| n=$(bench_one "$a" normal) | |
| r=$(bench_one "$a" reflink) | |
| printf '%-28s %9ss %9ss %8sx\n' "$(basename "$a")" "$n" "$r" \ | |
| "$(awk "BEGIN { printf \"%.1f\", $n / $r }")" | |
| done | |
| rm -rf "$dir/x" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment