#!/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
}
