This repository has been archived on 2026-07-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
lines/perf.sh
T
2026-07-04 20:44:28 +02:00

145 lines
4.8 KiB
Bash
Executable File

#!/bin/sh
# Reproducible local performance proof for lines.
# req: performance/002
# req: performance/003
# req: verification/003
set -eu
bin=${1:-zig-out/bin/lines}
line_count=${LINES_PERF_LINES:-10000000}
tmp=${TMPDIR:-/tmp}/lines-perf.$$
data=$tmp.data
trap 'rm -f "$tmp".*' EXIT HUP INT TERM
case $line_count in
''|*[!0-9]*) echo 'perf: LINES_PERF_LINES must be a positive decimal integer' >&2; exit 2 ;;
esac
if [ "$line_count" -eq 0 ]; then
echo 'perf: LINES_PERF_LINES must be greater than zero' >&2
exit 2
fi
if [ "$line_count" -lt 10000000 ] && [ "${LINES_PERF_ALLOW_SMALL:-0}" != 1 ]; then
echo 'perf: set LINES_PERF_ALLOW_SMALL=1 for a non-requirement quick run' >&2
exit 2
fi
if [ ! -x "$bin" ]; then
echo "perf: executable not found: $bin" >&2
exit 2
fi
now_ns() {
ns=$(date +%s%N 2>/dev/null || true)
case $ns in
*[!0-9]*|'') printf '%s000000000\n' "$(date +%s)" ;;
*) printf '%s\n' "$ns" ;;
esac
}
measure_proc() {
label=$1
shift
start_ns=$(now_ns)
"$@" >/dev/null &
pid=$!
peak_kb=0
while kill -0 "$pid" 2>/dev/null; do
rss_kb=$(awk '/^VmRSS:/ { print $2; found = 1; exit } END { if (!found) print 0 }' "/proc/$pid/status" 2>/dev/null || printf '0\n')
if [ "$rss_kb" -gt "$peak_kb" ]; then
peak_kb=$rss_kb
fi
sleep 0.01 2>/dev/null || sleep 1
done
wait "$pid"
end_ns=$(now_ns)
elapsed=$(awk -v start="$start_ns" -v end="$end_ns" 'BEGIN { printf "%.3f", (end - start) / 1000000000 }')
printf '%s\t%s\t%s\n' "$label" "$elapsed" "$peak_kb"
}
measure_time() {
label=$1
shift
metrics=$tmp.$label.time
case $time_mode in
gnu)
"$time_bin" -f '%e\t%M' -o "$metrics" "$@" >/dev/null
elapsed=$(awk 'BEGIN { FS = "\t" } { print $1; exit }' "$metrics")
rss_kb=$(awk 'BEGIN { FS = "\t" } { print $2; exit }' "$metrics")
;;
bsd)
"$time_bin" -l -o "$metrics" "$@" >/dev/null
elapsed=$(awk '/ real$/ { print $1; exit }' "$metrics")
rss_bytes=$(awk '/maximum resident set size/ { print $1; exit }' "$metrics")
rss_kb=$(awk -v bytes="$rss_bytes" 'BEGIN { printf "%.0f", (bytes + 1023) / 1024 }')
;;
esac
printf '%s\t%s\t%s\n' "$label" "$elapsed" "$rss_kb"
}
measure() {
case $measure_mode in
time) measure_time "$@" ;;
proc) measure_proc "$@" ;;
esac
}
measure_mode=
for candidate in /usr/bin/time /bin/time gtime; do
if command -v "$candidate" >/dev/null 2>&1; then
if "$candidate" -f '%e\t%M' -o "$tmp.probe" true 2>/dev/null; then
time_bin=$candidate
time_mode=gnu
measure_mode=time
break
fi
if "$candidate" -l -o "$tmp.probe" true 2>/dev/null; then
time_bin=$candidate
time_mode=bsd
measure_mode=time
break
fi
fi
done
if [ -z "$measure_mode" ]; then
if [ -r /proc/$$/status ]; then
measure_mode=proc
else
echo 'perf: peak RSS needs GNU/BSD time or Linux /proc status sampling' >&2
exit 2
fi
fi
start=$((line_count - 99))
end=$line_count
printf 'perf: generating %s lines in %s\n' "$line_count" "$data" >&2
awk -v n="$line_count" 'BEGIN { for (i = 1; i <= n; i++) printf "%08d abcdefghijklmnopqrstuvwxyz\n", i }' > "$data"
actual_lines=$(wc -l < "$data" | tr -d ' ')
bytes=$(wc -c < "$data" | tr -d ' ')
if [ "$actual_lines" -ne "$line_count" ]; then
echo "perf: generated $actual_lines lines, expected $line_count" >&2
exit 1
fi
printf 'tool\telapsed_seconds\tpeak_rss_kb\tlines\tbytes\tstart\tend\tcommand\n'
lines_row=$(measure lines "$bin" "$data" "$start" "$end")
sed_row=$(measure sed sed -n "${start},${end}p" "$data")
lines_elapsed=$(printf '%s\n' "$lines_row" | awk 'BEGIN { FS = "\t" } { print $2 }')
lines_rss=$(printf '%s\n' "$lines_row" | awk 'BEGIN { FS = "\t" } { print $3 }')
sed_elapsed=$(printf '%s\n' "$sed_row" | awk 'BEGIN { FS = "\t" } { print $2 }')
sed_rss=$(printf '%s\n' "$sed_row" | awk 'BEGIN { FS = "\t" } { print $3 }')
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s %s %s %s\n' lines "$lines_elapsed" "$lines_rss" "$line_count" "$bytes" "$start" "$end" "$bin" "$data" "$start" "$end"
printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\tsed -n %s,%sp %s\n' sed "$sed_elapsed" "$sed_rss" "$line_count" "$bytes" "$start" "$end" "$start" "$end" "$data"
awk -v le="$lines_elapsed" -v se="$sed_elapsed" 'BEGIN { if (se <= 0 || le > se * 2.0) exit 1 }' || {
echo "perf: lines elapsed ${lines_elapsed}s is not within 2x sed ${sed_elapsed}s" >&2
exit 1
}
awk -v lr="$lines_rss" -v sr="$sed_rss" 'BEGIN { if (sr > 0 && lr > sr * 2.0) exit 1 }' || {
echo "perf: lines RSS ${lines_rss} KiB is not within 2x sed ${sed_rss} KiB" >&2
exit 1
}