diff --git a/.github/scripts/bench-reth-build.sh b/.github/scripts/bench-reth-build.sh index 56a389a9f8d..5fa9a76522b 100755 --- a/.github/scripts/bench-reth-build.sh +++ b/.github/scripts/bench-reth-build.sh @@ -1,24 +1,21 @@ #!/usr/bin/env bash # -# Builds (or fetches from cache) reth binaries for benchmarking. +# Builds reth binaries for benchmarking from local source only. # -# Usage: bench-reth-build.sh [branch-sha] +# Usage: bench-reth-build.sh # -# baseline — build/fetch the baseline binary at (merge-base) +# baseline — build the baseline binary at (merge-base) # source-dir must be checked out at -# feature — build/fetch the candidate binary + reth-bench at +# feature — build the candidate binary + reth-bench at # source-dir must be checked out at -# optional branch-sha is the PR head commit for cache key # # Outputs: # baseline: /target/profiling/reth (or reth-bb if BENCH_BIG_BLOCKS=true) # feature: /target/profiling/reth (or reth-bb), reth-bench installed to cargo bin # -# Required: mc (MinIO client) with a configured alias # Optional env: BENCH_BIG_BLOCKS (true/false) — build reth-bb instead of reth set -euxo pipefail -MC="mc" MODE="$1" SOURCE_DIR="$2" COMMIT="$3" @@ -42,110 +39,38 @@ if [ "${BENCH_TRACY:-off}" != "off" ]; then EXTRA_RUSTFLAGS=" -C force-frame-pointers=yes" fi -# Cache suffix: hash of features+rustflags so different build configs get separate cache entries -if [ -n "$EXTRA_FEATURES" ] || [ -n "$EXTRA_RUSTFLAGS" ]; then - BUILD_SUFFIX="-$(echo "${EXTRA_FEATURES}${EXTRA_RUSTFLAGS}" | sha256sum | cut -c1-12)" -else - BUILD_SUFFIX="" -fi +# Build the requested node binary with the benchmark profile. +build_node_binary() { + local features_arg="" + local workspace_arg="" -# Verify a cached reth binary was built from the expected commit. -# `reth --version` outputs "Commit SHA: " on its own line. -verify_binary() { - local binary="$1" expected_commit="$2" - local version binary_sha - version=$("$binary" --version 2>/dev/null) || return 1 - binary_sha=$(echo "$version" | sed -n 's/^Commit SHA: *//p') - if [ -z "$binary_sha" ]; then - echo "Warning: could not extract commit SHA from version output" - return 1 + cd "$SOURCE_DIR" + if [ -n "$EXTRA_FEATURES" ]; then + # --workspace is needed for cross-package feature syntax (tracy-client/ondemand) + features_arg="--features ${EXTRA_FEATURES}" + workspace_arg="--workspace" fi - if [ "$binary_sha" = "$expected_commit" ]; then - return 0 - fi - echo "Cache mismatch: binary built from ${binary_sha} but expected ${expected_commit}" - return 1 -} -upload_cache_artifact() { - local source="$1" destination="$2" - if ! $MC cp "$source" "$destination"; then - echo "::warning::Failed to upload binary cache artifact to ${destination}; continuing without remote cache write" - fi + # shellcheck disable=SC2086 + RUSTFLAGS="-C target-cpu=native${EXTRA_RUSTFLAGS}" \ + cargo build --profile profiling $NODE_PKG $workspace_arg $features_arg } case "$MODE" in baseline|main) - BUCKET="minio/reth-binaries/${COMMIT}${BUILD_SUFFIX}" - mkdir -p "${SOURCE_DIR}/target/profiling" - - CACHE_VALID=false - if $MC stat --no-list "${BUCKET}/${NODE_BIN}" &>/dev/null; then - echo "Cache hit for baseline (${COMMIT}), downloading ${NODE_BIN}..." - if $MC cp "${BUCKET}/${NODE_BIN}" "${SOURCE_DIR}/target/profiling/${NODE_BIN}" && \ - chmod +x "${SOURCE_DIR}/target/profiling/${NODE_BIN}" && \ - verify_binary "${SOURCE_DIR}/target/profiling/${NODE_BIN}" "${COMMIT}"; then - CACHE_VALID=true - else - echo "Cached baseline binary is stale or download failed, rebuilding..." - fi - fi - if [ "$CACHE_VALID" = false ]; then - echo "Building baseline ${NODE_BIN} (${COMMIT}) from source..." - cd "${SOURCE_DIR}" - FEATURES_ARG="" - WORKSPACE_ARG="" - if [ -n "$EXTRA_FEATURES" ]; then - # --workspace is needed for cross-package feature syntax (tracy-client/ondemand) - FEATURES_ARG="--features ${EXTRA_FEATURES}" - WORKSPACE_ARG="--workspace" - fi - # shellcheck disable=SC2086 - RUSTFLAGS="-C target-cpu=native${EXTRA_RUSTFLAGS}" \ - cargo build --profile profiling $NODE_PKG $WORKSPACE_ARG $FEATURES_ARG - upload_cache_artifact "target/profiling/${NODE_BIN}" "${BUCKET}/${NODE_BIN}" - fi + echo "Building baseline ${NODE_BIN} (${COMMIT}) from source..." + build_node_binary ;; feature|branch) - BRANCH_SHA="${4:-$COMMIT}" - BUCKET="minio/reth-binaries/${BRANCH_SHA}${BUILD_SUFFIX}" - - CACHE_VALID=false - if $MC stat --no-list "${BUCKET}/${NODE_BIN}" &>/dev/null && $MC stat --no-list "${BUCKET}/reth-bench" &>/dev/null; then - echo "Cache hit for ${BRANCH_SHA}, downloading binaries..." - mkdir -p "${SOURCE_DIR}/target/profiling" - if $MC cp "${BUCKET}/${NODE_BIN}" "${SOURCE_DIR}/target/profiling/${NODE_BIN}" && \ - $MC cp "${BUCKET}/reth-bench" /home/ubuntu/.cargo/bin/reth-bench && \ - chmod +x "${SOURCE_DIR}/target/profiling/${NODE_BIN}" /home/ubuntu/.cargo/bin/reth-bench && \ - verify_binary "${SOURCE_DIR}/target/profiling/${NODE_BIN}" "${COMMIT}"; then - CACHE_VALID=true - else - echo "Cached feature binary is stale or download failed, rebuilding..." - fi - fi - if [ "$CACHE_VALID" = false ]; then - echo "Building feature ${NODE_BIN} (${COMMIT}) from source..." - cd "${SOURCE_DIR}" - rustup show active-toolchain || rustup default stable - if [ -n "$EXTRA_FEATURES" ]; then - # Can't use `make profiling` when adding features; build explicitly - # --workspace is needed for cross-package feature syntax (tracy-client/ondemand) - RUSTFLAGS="-C target-cpu=native${EXTRA_RUSTFLAGS}" \ - cargo build --profile profiling --workspace $NODE_PKG --features "${EXTRA_FEATURES}" - else - # shellcheck disable=SC2086 - RUSTFLAGS="-C target-cpu=native${EXTRA_RUSTFLAGS}" \ - cargo build --profile profiling $NODE_PKG - fi - make install-reth-bench - upload_cache_artifact "target/profiling/${NODE_BIN}" "${BUCKET}/${NODE_BIN}" - upload_cache_artifact "$(which reth-bench)" "${BUCKET}/reth-bench" - fi + echo "Building feature ${NODE_BIN} (${COMMIT}) from source..." + rustup show active-toolchain || rustup default stable + build_node_binary + make -C "$SOURCE_DIR" install-reth-bench ;; *) - echo "Usage: $0 [branch-sha]" + echo "Usage: $0 " exit 1 ;; esac diff --git a/.github/scripts/bench-reth-local.sh b/.github/scripts/bench-reth-local.sh index 1f75498265e..4d2565592d8 100755 --- a/.github/scripts/bench-reth-local.sh +++ b/.github/scripts/bench-reth-local.sh @@ -2,7 +2,7 @@ # # local-reth-bench.sh — Run the reth Engine API benchmark locally. # -# Replicates the CI bench.yml workflow (build, snapshot, system tuning, +# Replicates the CI bench.yml workflow (build, local snapshot validation, system tuning, # interleaved B-F-F-B execution, summary, charts) without any GitHub # Actions glue (no PR comments, no artifact upload, no Slack). # @@ -21,15 +21,17 @@ # Requires: the reth repo at RETH_REPO (default: ~/reth) # # Dependencies (install before first run): -# mc (MinIO client), schelk, cpupower, taskset, stdbuf, python3, curl, -# make, uv, pzstd, jq, Rust toolchain (cargo/rustup) +# schelk, cpupower, taskset, stdbuf, python3, curl, +# make, uv, jq, Rust toolchain (cargo/rustup) +# Optional: +# mc for Tracy profile upload # # The script delegates to the existing bench-reth-*.sh scripts in the reth # repo for the actual build, snapshot, and run steps. set -euxo pipefail # ── PATH ────────────────────────────────────────────────────────────── -# Ensure cargo and user-local bins (mc, uv) are visible +# Ensure cargo and user-local bins (uv) are visible export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$PATH" # ── Defaults ────────────────────────────────────────────────────────── @@ -106,7 +108,7 @@ fi # ── Check dependencies ─────────────────────────────────────────────── missing=() -for cmd in mc schelk cpupower taskset stdbuf python3 curl make uv pzstd jq cargo; do +for cmd in schelk cpupower taskset stdbuf python3 curl make uv jq cargo; do command -v "$cmd" &>/dev/null || missing+=("$cmd") done if [ ${#missing[@]} -gt 0 ]; then @@ -238,19 +240,14 @@ echo " Baseline src : $BASELINE_SRC" echo " Feature src : $FEATURE_SRC" echo -# ── Step 3: Check / download snapshot ──────────────────────────────── -echo "▸ Checking snapshot..." +# ── Step 3: Validate local snapshot ────────────────────────────────── +echo "▸ Validating local snapshot..." cd "$RETH_REPO" -SNAPSHOT_NEEDED=false -if ! "${SCRIPTS_DIR}/bench-reth-snapshot.sh" --check; then - SNAPSHOT_NEEDED=true - echo " Snapshot needs update." -else - echo " Snapshot is up-to-date." -fi +"${SCRIPTS_DIR}/bench-reth-snapshot.sh" +echo " Snapshot is ready." echo -# ── Step 4: Build binaries (+ snapshot download) in parallel ───────── +# ── Step 4: Build binaries in parallel ─────────────────────────────── echo "▸ Building binaries (parallel)..." cd "$RETH_REPO" @@ -262,19 +259,11 @@ PID_BASELINE=$! "${SCRIPTS_DIR}/bench-reth-build.sh" feature "$FEATURE_SRC" "$FEATURE_SHA" & PID_FEATURE=$! -PID_SNAPSHOT= -if [ "$SNAPSHOT_NEEDED" = "true" ]; then - echo " Also downloading snapshot in parallel..." - "${SCRIPTS_DIR}/bench-reth-snapshot.sh" & - PID_SNAPSHOT=$! -fi - wait $PID_BASELINE || FAIL=1 wait $PID_FEATURE || FAIL=1 -[ -n "$PID_SNAPSHOT" ] && { wait $PID_SNAPSHOT || FAIL=1; } if [ $FAIL -ne 0 ]; then - echo "Error: one or more parallel tasks failed (builds / snapshot)" + echo "Error: one or more build tasks failed" exit 1 fi echo " Binaries built successfully." diff --git a/.github/scripts/bench-reth-run.sh b/.github/scripts/bench-reth-run.sh index 9a757274d93..94dd512f2ee 100755 --- a/.github/scripts/bench-reth-run.sh +++ b/.github/scripts/bench-reth-run.sh @@ -88,10 +88,16 @@ trap cleanup EXIT # Stop any leftover reth process in the scope, then recover schelk state. sudo systemctl stop "$RETH_SCOPE" 2>/dev/null || true sudo systemctl reset-failed "$RETH_SCOPE" 2>/dev/null || true -sudo schelk recover -y --kill || true +sudo schelk recover -y --kill || sudo schelk full-recover -y || true # Mount -sudo schelk mount -y +sudo schelk mount -y || true +if [ ! -d "$DATADIR/db" ] || [ ! -d "$DATADIR/static_files" ]; then + echo "::error::Failed to mount benchmark datadir at ${DATADIR}" + ls -la "$SCHELK_MOUNT" || true + ls -la "$DATADIR" || true + exit 1 +fi sync sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches' echo "=== Cache state after drop ===" diff --git a/.github/scripts/bench-reth-snapshot.sh b/.github/scripts/bench-reth-snapshot.sh index 96b515235fd..5d8b883e544 100755 --- a/.github/scripts/bench-reth-snapshot.sh +++ b/.github/scripts/bench-reth-snapshot.sh @@ -1,197 +1,56 @@ #!/usr/bin/env bash # -# Downloads the latest snapshot into the schelk volume using -# `reth download` with progress reporting to the GitHub PR comment. -# -# Skips the download if the manifest content hasn't changed since -# the last successful download (checked via SHA-256 of the manifest). +# Validates that the benchmark snapshot has already been populated into the +# local schelk volume. # # Usage: bench-reth-snapshot.sh [--check] -# --check Only check if a download is needed; exits 0 if up-to-date, 10 if not. +# --check Exit 0 if the local snapshot is ready, 10 if it is missing. # # Required env: -# SCHELK_MOUNT – schelk mount point (e.g. /reth-bench) -# BENCH_RETH_BINARY – path to the reth binary -# GITHUB_TOKEN – token for GitHub API calls (only for download) -# BENCH_COMMENT_ID – PR comment ID to update (optional) -# BENCH_REPO – owner/repo (e.g. paradigmxyz/reth) -# BENCH_JOB_URL – link to the Actions job -# BENCH_ACTOR – user who triggered the benchmark -# BENCH_CONFIG – config summary line +# SCHELK_MOUNT – schelk mount point (e.g. /reth-bench) +# Optional env: +# BENCH_BIG_BLOCKS – true when validating the big-blocks snapshot datadir +# BENCH_SNAPSHOT_NAME – expected snapshot label for log/error output set -euxo pipefail -MC="mc" +: "${SCHELK_MOUNT:?SCHELK_MOUNT must be set}" + DATADIR_NAME="datadir" -HASH_MODE_SUFFIX="" if [ "${BENCH_BIG_BLOCKS:-false}" = "true" ]; then DATADIR_NAME="datadir-big-blocks" - HASH_MODE_SUFFIX="-big-blocks" fi DATADIR="$SCHELK_MOUNT/$DATADIR_NAME" -HASH_FILE="$HOME/.reth-bench-snapshot-hash${HASH_MODE_SUFFIX}" - -resolve_bucket() { - local candidate - for candidate in \ - "${BENCH_SNAPSHOT_BUCKET:-}" \ - "r2-reth-snapshots/reth-snapshots" \ - "minio/reth-snapshots"; do - if [ -n "$candidate" ] && $MC ls "$candidate" >/dev/null 2>&1; then - echo "$candidate" - return 0 - fi - done - - echo "::error::Failed to find a readable snapshot bucket via mc ls" - exit 2 -} - -resolve_snapshot_name() { - local bucket="$1" - - # Big-block benchmarks pin the base snapshot via BENCH_SNAPSHOT_NAME. +describe_snapshot() { if [ -n "${BENCH_SNAPSHOT_NAME:-}" ]; then - echo "$BENCH_SNAPSHOT_NAME" - return 0 - fi - - mapfile -t snapshots < <( - $MC ls "$bucket" 2>/dev/null \ - | awk '$NF ~ /\/$/ { print $NF }' \ - | sed 's:/$::' - ) - - if [ "${#snapshots[@]}" -lt 2 ]; then - echo "::error::Need at least two snapshots in ${bucket} to resolve the previous snapshot" - exit 2 + printf '%s' "${BENCH_SNAPSHOT_NAME}" + elif [ "${BENCH_BIG_BLOCKS:-false}" = "true" ]; then + printf '%s' 'big-block weekly snapshot' + else + printf '%s' 'benchmark snapshot' fi - - echo "${snapshots[$(( ${#snapshots[@]} - 2 ))]}" } -BUCKET="$(resolve_bucket)" -SNAPSHOT_NAME="$(resolve_snapshot_name "$BUCKET")" -MANIFEST_PATH="${SNAPSHOT_NAME}/manifest.json" -BUCKET_ALIAS="${BUCKET%%/*}" -BUCKET_PATH="${BUCKET#*/}" - -echo "Using snapshot bucket: ${BUCKET}" -echo "Using snapshot: ${SNAPSHOT_NAME}" - -# Fetch manifest and compute content hash for reliable freshness check -XTRACE_WAS_ENABLED=false -if [[ $- == *x* ]]; then - XTRACE_WAS_ENABLED=true - set +x -fi +snapshot_ready() { + [ -d "$DATADIR/db" ] && [ -d "$DATADIR/static_files" ] +} -if ! MANIFEST_CONTENT=$($MC cat "${BUCKET}/${MANIFEST_PATH}" 2>/dev/null); then - echo "::error::Failed to fetch snapshot manifest from ${BUCKET}/${MANIFEST_PATH}" - exit 2 -fi -ORIGINAL_BASE_URL=$(printf '%s' "$MANIFEST_CONTENT" | jq -r '.base_url // empty') -REMOTE_HASH=$(printf '%s' "$MANIFEST_CONTENT" | sha256sum | awk '{print $1}') +EXPECTED_SNAPSHOT="$(describe_snapshot)" -LOCAL_HASH="" -[ -f "$HASH_FILE" ] && LOCAL_HASH=$(cat "$HASH_FILE") +sudo schelk recover -y --kill || sudo schelk full-recover -y || true +sudo schelk mount -y || true -if [ "$REMOTE_HASH" = "$LOCAL_HASH" ]; then - echo "Snapshot is up-to-date (manifest hash: ${REMOTE_HASH:0:16}…)" +if snapshot_ready; then + echo "Found local ${EXPECTED_SNAPSHOT} at ${DATADIR}" exit 0 fi -echo "Snapshot needs update (local: ${LOCAL_HASH:+${LOCAL_HASH:0:16}…}${LOCAL_HASH:-}, remote: ${REMOTE_HASH:0:16}…)" +echo "::error::Missing local ${EXPECTED_SNAPSHOT} at ${DATADIR}. Benchmarks no longer download snapshots; pre-populate the local schelk data first." +ls -la "$SCHELK_MOUNT" || true +ls -la "$DATADIR" || true + if [ "${1:-}" = "--check" ]; then exit 10 fi -RETH="${BENCH_RETH_BINARY:?BENCH_RETH_BINARY must be set}" -if [ ! -x "$RETH" ]; then - echo "::error::reth binary not found or not executable at $RETH" - exit 1 -fi - -# Resolve the MinIO HTTP endpoint from the mc alias so reth can -# fetch archives over HTTP (the manifest's embedded base_url points -# to the cluster-internal address which is unreachable from runners). -MINIO_ENDPOINT=$($MC alias list "$BUCKET_ALIAS" --json 2>/dev/null | jq -r '.URL // empty') || true -if [ -z "$MINIO_ENDPOINT" ]; then - echo "::error::Failed to resolve snapshot endpoint from mc alias '${BUCKET_ALIAS}'" - exit 1 -fi - -MANIFEST_TMP=$(mktemp --suffix=.json) -trap 'rm -f -- "$MANIFEST_TMP"' EXIT -if [[ "$MINIO_ENDPOINT" == *".r2.cloudflarestorage.com" ]]; then - # R2's S3 endpoint is not the public object-download URL. Keep the manifest's - # published base_url (for example r2.dev or a custom domain) for anonymous GETs. - printf '%s' "$MANIFEST_CONTENT" > "$MANIFEST_TMP" -else - BASE_URL="${MINIO_ENDPOINT%/}/${BUCKET_PATH}/${SNAPSHOT_NAME}" - # Rewrite manifest's base_url with the runner-reachable endpoint. - printf '%s' "$MANIFEST_CONTENT" \ - | jq --arg base "$BASE_URL" '.base_url = $base' > "$MANIFEST_TMP" -fi -EFFECTIVE_BASE_URL=$(jq -r '.base_url // empty' "$MANIFEST_TMP") - -if [ "$XTRACE_WAS_ENABLED" = true ]; then - set -x -fi - -echo "Manifest base_url before rewrite: ${ORIGINAL_BASE_URL:-}" -if [[ "$MINIO_ENDPOINT" == *".r2.cloudflarestorage.com" ]]; then - echo "Using manifest base_url for R2 snapshot downloads" -fi -echo "Manifest base_url after rewrite: ${EFFECTIVE_BASE_URL:-}" - -# Prepare mount. If a previous run left the volume mounted, recover first. -sudo schelk recover -y --kill || true -sudo schelk mount -y -sudo rm -rf "$DATADIR" -sudo mkdir -p "$DATADIR" -# reth download runs as current user (not root), needs write access -sudo chown -R "$(id -u):$(id -g)" "$DATADIR" - -update_comment() { - local status="$1" - [ -z "${BENCH_COMMENT_ID:-}" ] && return 0 - local body - body="$(printf 'cc @%s\n\n🚀 Benchmark started! [View job](%s)\n\n⏳ **Status:** %s\n\n%s' \ - "$BENCH_ACTOR" "$BENCH_JOB_URL" "$status" "$BENCH_CONFIG")" - curl -sf -X PATCH \ - -H "Authorization: token ${GITHUB_TOKEN}" \ - -H "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/${BENCH_REPO}/issues/comments/${BENCH_COMMENT_ID}" \ - -d "$(jq -nc --arg body "$body" '{body: $body}')" \ - > /dev/null 2>&1 || true -} - -update_comment "Downloading snapshot…" - -# Download using reth download (manifest-path with rewritten base_url) -"$RETH" download \ - --manifest-path "$MANIFEST_TMP" \ - -y \ - --minimal \ - --datadir "$DATADIR" - -update_comment "Downloading snapshot… done" -echo "Snapshot download complete" - -# Sanity check: verify expected directories exist -if [ ! -d "$DATADIR/db" ] || [ ! -d "$DATADIR/static_files" ]; then - echo "::error::Snapshot download did not produce expected directory layout (missing db/ or static_files/)" - ls -la "$DATADIR" || true - exit 1 -fi - -# Promote the new snapshot to become the schelk baseline (virgin volume). -# This copies changed blocks from scratch → virgin so that future -# `schelk recover` calls restore to this new state. -sync -sudo schelk promote -y - -# Save manifest hash -echo "$REMOTE_HASH" > "$HASH_FILE" -echo "Snapshot promoted to schelk baseline (manifest hash: ${REMOTE_HASH:0:16}…)" +exit 1 diff --git a/.github/workflows/bench-scheduled.yml b/.github/workflows/bench-scheduled.yml index d5031a54ec5..8ade5e9fea2 100644 --- a/.github/workflows/bench-scheduled.yml +++ b/.github/workflows/bench-scheduled.yml @@ -307,12 +307,6 @@ jobs: linux-tools-"$(uname -r)" || \ sudo apt-get install -y --no-install-recommends linux-tools-generic - # mc (MinIO client) - if ! command -v mc &>/dev/null; then - curl -sSfL https://dl.min.io/client/mc/release/linux-amd64/mc -o "$HOME/.local/bin/mc" - chmod +x "$HOME/.local/bin/mc" - fi - # uv (Python package manager) if ! command -v uv &>/dev/null; then curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR="$HOME/.local/bin" sh @@ -340,7 +334,7 @@ jobs: echo "$HOME/.local/bin" >> "$GITHUB_PATH" echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" missing=() - for cmd in mc schelk cpupower taskset stdbuf python3 curl make uv pzstd jq; do + for cmd in schelk cpupower taskset stdbuf python3 curl make uv jq; do command -v "$cmd" &>/dev/null || missing+=("$cmd") done if [ ${#missing[@]} -gt 0 ]; then @@ -366,19 +360,9 @@ jobs: echo "feature-name=${BENCH_MODE}-${FEATURE_SHORT}" >> "$GITHUB_OUTPUT" echo "feature-ref=$FEATURE_REF" >> "$GITHUB_OUTPUT" - - name: Check if snapshot needs update + - name: Validate local snapshot id: snapshot-check - run: | - set +e - .github/scripts/bench-reth-snapshot.sh --check - rc=$? - set -e - case "$rc" in - 0) echo "needed=false" >> "$GITHUB_OUTPUT" ;; - 10) echo "needed=true" >> "$GITHUB_OUTPUT" ;; - *) echo "::error::Snapshot check failed (exit $rc)" - exit "$rc" ;; - esac + run: .github/scripts/bench-reth-snapshot.sh - name: Prepare source dirs run: | @@ -418,15 +402,6 @@ jobs: exit 1 fi - - name: Download snapshot - id: snapshot-download - if: steps.snapshot-check.outputs.needed == 'true' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BENCH_REPO: ${{ github.repository }} - BENCH_RETH_BINARY: ${{ github.workspace }}/../reth-feature/target/profiling/reth - run: .github/scripts/bench-reth-snapshot.sh - # System tuning for reproducible benchmarks - name: System setup run: | @@ -925,8 +900,8 @@ jobs: if (!token || !channel) return; const steps_status = [ + ['validating local snapshot', '${{ steps.snapshot-check.outcome }}'], ['building binaries', '${{ steps.build.outcome }}'], - ['downloading snapshot', '${{ steps.snapshot-download.outcome }}'], ['running baseline benchmark (1/2)', '${{ steps.run-baseline-1.outcome }}'], ['running feature benchmark (1/2)', '${{ steps.run-feature-1.outcome }}'], ['running feature benchmark (2/2)', '${{ steps.run-feature-2.outcome }}'], diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index ddcb4b88220..2428dc68c29 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -650,12 +650,6 @@ jobs: linux-tools-"$(uname -r)" || \ sudo apt-get install -y --no-install-recommends linux-tools-generic - # mc (MinIO client) - if ! command -v mc &>/dev/null; then - curl -sSfL https://dl.min.io/client/mc/release/linux-amd64/mc -o "$HOME/.local/bin/mc" - chmod +x "$HOME/.local/bin/mc" - fi - # uv (Python package manager) if ! command -v uv &>/dev/null; then curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR="$HOME/.local/bin" sh @@ -690,7 +684,7 @@ jobs: echo "$HOME/.local/bin" >> "$GITHUB_PATH" echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" missing=() - for cmd in mc schelk cpupower taskset stdbuf python3 curl make uv pzstd jq; do + for cmd in schelk cpupower taskset stdbuf python3 curl make uv jq; do command -v "$cmd" &>/dev/null || missing+=("$cmd") done if [ ${#missing[@]} -gt 0 ]; then @@ -766,61 +760,45 @@ jobs: core.setOutput('feature-ref', featureRef); core.setOutput('feature-name', featureName); - - name: Check big-blocks freshness + - name: Validate local big blocks if: env.BENCH_BIG_BLOCKS == 'true' id: big-blocks-check run: | set -euo pipefail - MC="mc --config-dir /home/ubuntu/.mc" - MANIFEST="minio/reth-snapshots/reth-1-minimal-stable-big-blocks.json" - HASH_FILE="$HOME/.reth-bench-big-blocks-hash" - echo "Fetching big-blocks manifest from $MANIFEST..." - BB_MANIFEST=$($MC cat "$MANIFEST" 2>/dev/null) || { - echo "::error::Failed to fetch big-blocks manifest from $MANIFEST" + BIG_BLOCKS_DIR="$HOME/.reth-bench-big-blocks" + PAYLOAD_DIR="$BIG_BLOCKS_DIR/payloads" + MANIFEST="$BIG_BLOCKS_DIR/manifest.json" + echo "BENCH_BIG_BLOCKS_DIR=${BIG_BLOCKS_DIR}" >> "$GITHUB_ENV" + + if [ ! -f "$MANIFEST" ]; then + echo "::error::Missing local big-blocks manifest at $MANIFEST" exit 1 - } - BASE_SNAPSHOT=$(echo "$BB_MANIFEST" | jq -r '.base_snapshot // empty') + fi + + BASE_SNAPSHOT=$(jq -r '.base_snapshot // empty' "$MANIFEST") if [ -z "$BASE_SNAPSHOT" ]; then echo "::error::Big-blocks manifest missing base_snapshot field" exit 1 fi - echo "Big-blocks base snapshot: $BASE_SNAPSHOT" - echo "BENCH_SNAPSHOT_NAME=${BASE_SNAPSHOT}" >> "$GITHUB_ENV" - REMOTE_HASH=$(echo "$BB_MANIFEST" | sha256sum | awk '{print $1}') - LOCAL_HASH="" - [ -f "$HASH_FILE" ] && LOCAL_HASH=$(cat "$HASH_FILE") - if [ "$REMOTE_HASH" = "$LOCAL_HASH" ]; then - echo "Big blocks up-to-date (hash: ${REMOTE_HASH:0:16}…)" - echo "needed=false" >> "$GITHUB_OUTPUT" - else - echo "Big blocks need update (local: ${LOCAL_HASH:+${LOCAL_HASH:0:16}…}${LOCAL_HASH:-}, remote: ${REMOTE_HASH:0:16}…)" - echo "needed=true" >> "$GITHUB_OUTPUT" - echo "remote-hash=${REMOTE_HASH}" >> "$GITHUB_OUTPUT" + if [ ! -d "$PAYLOAD_DIR" ]; then + echo "::error::Missing local big-block payload directory at $PAYLOAD_DIR" + exit 1 fi - - name: Check if snapshot needs update + PAYLOAD_COUNT=$(find "$PAYLOAD_DIR" -name '*.json' | wc -l) + if [ "$PAYLOAD_COUNT" -eq 0 ]; then + echo "::error::No payload files found in $PAYLOAD_DIR" + exit 1 + fi + + echo "Big-blocks base snapshot: $BASE_SNAPSHOT" + echo "Payload files: $PAYLOAD_COUNT" + echo "BENCH_SNAPSHOT_NAME=${BASE_SNAPSHOT}" >> "$GITHUB_ENV" + + - name: Validate local snapshot id: snapshot-check - run: | - set +e - .github/scripts/bench-reth-snapshot.sh --check - rc=$? - set -e - case "$rc" in - 0) echo "needed=false" >> "$GITHUB_OUTPUT" ;; - 10) echo "needed=true" >> "$GITHUB_OUTPUT" ;; - *) echo "::error::Snapshot check failed (exit $rc)" - exit "$rc" ;; - esac - - - name: Update status (snapshot needed) - if: env.BENCH_COMMENT_ID && steps.snapshot-check.outputs.needed == 'true' - uses: actions/github-script@v9 - with: - github-token: ${{ secrets.DEREK_PAT }} - script: | - const s = require('./.github/scripts/bench-update-status.js'); - await s({github, context, status: 'Building binaries (snapshot update pending)...'}); + run: .github/scripts/bench-reth-snapshot.sh - name: Prepare source dirs run: | @@ -862,15 +840,6 @@ jobs: exit 1 fi - - name: Download snapshot - id: snapshot-download - if: steps.snapshot-check.outputs.needed == 'true' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - BENCH_REPO: ${{ github.repository }} - BENCH_RETH_BINARY: ${{ github.workspace }}/../reth-feature/target/profiling/${{ needs.reth-bench-ack.outputs.big-blocks == 'true' && 'reth-bb' || 'reth' }} - run: .github/scripts/bench-reth-snapshot.sh - # System tuning for reproducible benchmarks - name: System setup run: | @@ -941,45 +910,6 @@ jobs: rm -rf "$BENCH_WORK_DIR" mkdir -p "$BENCH_WORK_DIR" - - name: Download big blocks - if: env.BENCH_BIG_BLOCKS == 'true' - run: | - set -euo pipefail - BIG_BLOCKS_DIR="$HOME/.reth-bench-big-blocks" - echo "BENCH_BIG_BLOCKS_DIR=${BIG_BLOCKS_DIR}" >> "$GITHUB_ENV" - if [ "${{ steps.big-blocks-check.outputs.needed }}" = "false" ]; then - echo "Big blocks cached at $BIG_BLOCKS_DIR, skipping download" - echo "Payload files: $(find "$BIG_BLOCKS_DIR/payloads" -name '*.json' | wc -l)" - exit 0 - fi - MC="mc --config-dir /home/ubuntu/.mc" - MANIFEST="minio/reth-snapshots/reth-1-minimal-stable-big-blocks.json" - rm -rf "$BIG_BLOCKS_DIR"; mkdir -p "$BIG_BLOCKS_DIR" - - # Download and parse manifest - echo "Downloading manifest from $MANIFEST..." - $MC cat "$MANIFEST" > "$BIG_BLOCKS_DIR/manifest.json" - UPLOAD_PATH=$(jq -r '.upload_path' "$BIG_BLOCKS_DIR/manifest.json") - COUNT=$(jq -r '.count' "$BIG_BLOCKS_DIR/manifest.json") - TARGET_GAS=$(jq -r '.target_gas' "$BIG_BLOCKS_DIR/manifest.json") - echo "Manifest: count=$COUNT, target_gas=$TARGET_GAS, archive=$UPLOAD_PATH" - - # Download and extract archive - ARCHIVE="minio/$UPLOAD_PATH" - echo "Downloading big blocks from $ARCHIVE..." - $MC cat "$ARCHIVE" | pzstd -d -p 6 | tar -xf - -C "$BIG_BLOCKS_DIR" - echo "Big blocks downloaded to $BIG_BLOCKS_DIR" - - # Verify expected directory structure - if [ ! -d "$BIG_BLOCKS_DIR/payloads" ]; then - echo "::error::Big blocks archive missing expected payloads/ directory" - ls -laR "$BIG_BLOCKS_DIR" - exit 1 - fi - echo "Payload files: $(find "$BIG_BLOCKS_DIR/payloads" -name '*.json' | wc -l)" - # Save manifest hash for freshness check on next run - echo "${{ steps.big-blocks-check.outputs.remote-hash }}" > "$HOME/.reth-bench-big-blocks-hash" - - name: Start metrics proxy run: | BENCH_ID="ci-${{ github.run_id }}" @@ -1374,9 +1304,11 @@ jobs: github-token: ${{ secrets.DEREK_PAT }} script: | const abba = (process.env.BENCH_ABBA || 'true') !== 'false'; + const bigBlocks = process.env.BENCH_BIG_BLOCKS === 'true'; const steps_status = [ + ...(bigBlocks ? [['validating local big-block data', '${{ steps.big-blocks-check.outcome }}']] : []), + ['validating local snapshot', '${{ steps.snapshot-check.outcome }}'], ['building binaries', '${{ steps.build.outcome }}'], - ['downloading snapshot', '${{ steps.snapshot-download.outcome }}'], ['running baseline benchmark (1/2)', '${{ steps.run-baseline-1.outcome }}'], ['running feature benchmark (1/2)', '${{ steps.run-feature-1.outcome }}'], ...(abba ? [['running feature benchmark (2/2)', '${{ steps.run-feature-2.outcome }}']] : []), @@ -1410,9 +1342,11 @@ jobs: with: script: | const abba = (process.env.BENCH_ABBA || 'true') !== 'false'; + const bigBlocks = process.env.BENCH_BIG_BLOCKS === 'true'; const steps_status = [ + ...(bigBlocks ? [['validating local big-block data', '${{ steps.big-blocks-check.outcome }}']] : []), + ['validating local snapshot', '${{ steps.snapshot-check.outcome }}'], ['building binaries', '${{ steps.build.outcome }}'], - ['downloading snapshot', '${{ steps.snapshot-download.outcome }}'], ['running baseline benchmark (1/2)', '${{ steps.run-baseline-1.outcome }}'], ['running feature benchmark (1/2)', '${{ steps.run-feature-1.outcome }}'], ...(abba ? [['running feature benchmark (2/2)', '${{ steps.run-feature-2.outcome }}']] : []),