mirror of
https://github.com/logos-blockchain/research.git
synced 2026-08-07 11:43:20 +00:00
120 lines
5.5 KiB
Bash
120 lines
5.5 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# Run the ENTIRE Equi-X benchmark pipeline end to end:
|
||
|
|
# 1. bootstrap dependencies + build both runners (scripts/setup.sh)
|
||
|
|
# 2. harness unit tests
|
||
|
|
# 3. main benchmark: C vs Rust across all operations, incl. the DoS-protection
|
||
|
|
# verdict, with the cross-implementation correctness gate; the --full
|
||
|
|
# profile additionally measures sustained concurrency (saturation ladder)
|
||
|
|
# and the mining rate vs difficulty
|
||
|
|
# 4. compiler-flag variants: build a gcc/clang/-O matrix and compare them
|
||
|
|
#
|
||
|
|
# Usage:
|
||
|
|
# ./scripts/run_all.sh # quick profile (smoke config; a few minutes)
|
||
|
|
# ./scripts/run_all.sh --full # deep sweep (full config + effort sweep; longer)
|
||
|
|
# ./scripts/run_all.sh --out DIR # output base dir (default: results/)
|
||
|
|
# ./scripts/run_all.sh --no-variants # skip the compiler-flag matrix
|
||
|
|
# ./scripts/run_all.sh --no-setup # assume deps already installed/built
|
||
|
|
# ./scripts/run_all.sh --no-tests # skip the unit tests
|
||
|
|
set -uo pipefail
|
||
|
|
|
||
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
|
|
cd "$ROOT"
|
||
|
|
export PYTHONPATH="$ROOT/harness${PYTHONPATH:+:$PYTHONPATH}"
|
||
|
|
|
||
|
|
PROFILE=quick
|
||
|
|
OUT=results
|
||
|
|
DO_SETUP=1
|
||
|
|
DO_VARIANTS=1
|
||
|
|
DO_TESTS=1
|
||
|
|
|
||
|
|
while [ $# -gt 0 ]; do
|
||
|
|
case "$1" in
|
||
|
|
--full) PROFILE=full ;;
|
||
|
|
--quick) PROFILE=quick ;;
|
||
|
|
--out) [ $# -ge 2 ] || { echo "error: --out requires a directory argument" >&2; exit 2; }
|
||
|
|
OUT="$2"; shift ;;
|
||
|
|
--out=*) OUT="${1#*=}" ;;
|
||
|
|
--no-setup) DO_SETUP=0 ;;
|
||
|
|
--no-variants) DO_VARIANTS=0 ;;
|
||
|
|
--no-tests) DO_TESTS=0 ;;
|
||
|
|
-h|--help) sed -n '2,/^set -uo/p' "$0" | sed '$d'; exit 0 ;;
|
||
|
|
*) echo "unknown argument: $1" >&2; exit 2 ;;
|
||
|
|
esac
|
||
|
|
shift
|
||
|
|
done
|
||
|
|
|
||
|
|
MAIN_CONFIG="configs/smoke.toml"
|
||
|
|
[ "$PROFILE" = full ] && MAIN_CONFIG="configs/full.toml"
|
||
|
|
# Prefer the project venv scripts/setup.sh creates: it has the harness + pytest
|
||
|
|
# installed and sidesteps PEP-668 "externally-managed" pip failures on Linux.
|
||
|
|
PY="python3"
|
||
|
|
[ -x "$ROOT/.venv/bin/python" ] && PY="$ROOT/.venv/bin/python"
|
||
|
|
BENCH="$PY -m equix_bench"
|
||
|
|
fail() { echo "ERROR: $*" >&2; exit 1; }
|
||
|
|
|
||
|
|
# Ctrl+C: report the interruption plainly and exit 130, rather than letting the
|
||
|
|
# child's non-zero exit trip a misleading "ERROR: ... failed". The harness kills
|
||
|
|
# its own runner subprocesses on SIGINT; this trap just makes the pipeline's own
|
||
|
|
# exit clean. 128+SIGINT(2) = 130, the conventional interrupted-by-Ctrl+C code.
|
||
|
|
on_interrupt() { echo; echo "Interrupted (Ctrl+C) — stopping the pipeline." >&2; exit 130; }
|
||
|
|
trap on_interrupt INT
|
||
|
|
|
||
|
|
echo "======================================================================"
|
||
|
|
echo " Equi-X full pipeline profile=$PROFILE out=$OUT/"
|
||
|
|
echo "======================================================================"
|
||
|
|
|
||
|
|
if [ "$DO_SETUP" = 1 ]; then
|
||
|
|
echo; echo "### [1/4] Bootstrap dependencies + build runners"
|
||
|
|
./scripts/setup.sh || fail "setup.sh failed"
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ "$DO_TESTS" = 1 ]; then
|
||
|
|
echo; echo "### [2/4] Harness unit tests"
|
||
|
|
# Ensure pytest is importable. Externally-managed interpreters (PEP 668, e.g.
|
||
|
|
# Homebrew/Debian Python) reject a plain `pip install`, so fall back through
|
||
|
|
# --user and finally --break-system-packages before giving up.
|
||
|
|
# With the venv from setup.sh, pytest is already present. Otherwise fall back
|
||
|
|
# through --user and --break-system-packages before giving up.
|
||
|
|
if ! $PY -c 'import pytest' >/dev/null 2>&1; then
|
||
|
|
$PY -m pip install -q pytest >/dev/null 2>&1 \
|
||
|
|
|| $PY -m pip install -q --user pytest >/dev/null 2>&1 \
|
||
|
|
|| $PY -m pip install -q --break-system-packages pytest >/dev/null 2>&1 \
|
||
|
|
|| true
|
||
|
|
fi
|
||
|
|
if $PY -c 'import pytest' >/dev/null 2>&1; then
|
||
|
|
$PY -m pytest -q harness/tests || fail "unit tests failed"
|
||
|
|
else
|
||
|
|
echo " WARNING: could not install pytest; skipping unit tests." >&2
|
||
|
|
echo " Fix: re-run ./scripts/setup.sh (creates .venv with pytest), or:" >&2
|
||
|
|
echo " python3 -m pip install --break-system-packages pytest" >&2
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo; echo "### [3/4] Main benchmark: C vs Rust (all ops + DoS-protection; --full adds concurrency + mining) [$MAIN_CONFIG]"
|
||
|
|
# cmd_run runs the interop cross-check internally and exits non-zero if it fails,
|
||
|
|
# so this step is also the correctness gate.
|
||
|
|
$BENCH run --config "$MAIN_CONFIG" --out "$OUT/main" || fail "main benchmark / cross-check failed"
|
||
|
|
|
||
|
|
if [ "$DO_VARIANTS" = 1 ]; then
|
||
|
|
echo; echo "### [4/4] Compiler-flag variants (gcc/clang x -O levels)"
|
||
|
|
./scripts/build_variants.sh || echo " (some variants failed to build; continuing with those that did)"
|
||
|
|
$BENCH run --config configs/compiler_flags.toml --out "$OUT/compiler_flags" \
|
||
|
|
|| echo " (compiler-flags run returned non-zero; see $OUT/compiler_flags/)"
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo; echo "======================================================================"
|
||
|
|
echo " Done. Reports:"
|
||
|
|
echo " $OUT/main/report.md C vs Rust: time, throughput, RSS, compile, effort, DoS"
|
||
|
|
[ "$DO_VARIANTS" = 1 ] && echo " $OUT/compiler_flags/report.md compiler-flag comparison"
|
||
|
|
echo " plots: $OUT/*/plots/*.png data: $OUT/*/results.csv"
|
||
|
|
# The --full profile also measures sustained parallel solve/verify capacity.
|
||
|
|
[ -f "$OUT/main/concurrency.csv" ] && \
|
||
|
|
echo " $OUT/main/concurrency.csv measured concurrency/saturation (solves/s, verify/s, knee)"
|
||
|
|
[ -f "$OUT/main/mining.csv" ] && \
|
||
|
|
echo " $OUT/main/mining.csv measured mining rate vs difficulty (tokens/s, 1-core + machine)"
|
||
|
|
# Surface the DoS verdict inline.
|
||
|
|
if [ -f "$OUT/main/report.md" ]; then
|
||
|
|
grep -h 'Verdict:' "$OUT/main/report.md" | sed 's/\*\*//g; s/^/ DoS → /'
|
||
|
|
fi
|
||
|
|
echo "======================================================================"
|