Initial import
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
#!/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
|
||||
}
|
||||
Reference in New Issue
Block a user