Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
[alias]
xtask = "run --package xtask --"
docs = "doc --workspace --all-features --no-deps"
b = "bench --package builder --bench coordinator --"
bs = "bench --package builder --bench coordinator -- --save-baseline"
bc = "bench --package builder --bench coordinator -- --baseline main --save-baseline pr"
bench = "bench --package builder --bench coordinator --"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here and below, there is no coordinator bench

bench-save = "bench --package builder --bench coordinator -- --save-baseline"
bench-cmp = "bench --package builder --bench coordinator -- --baseline main --save-baseline pr"
prof-build = "build --profile profiling --features jemalloc --bin world-chain"
prof-bench = "bench --profile profiling --package world-chain-builder --bench coordinator"

[env]
DEBUG = "info,flashblocks=debug,world_chain=info"
Expand Down
84 changes: 84 additions & 0 deletions .github/scripts/build_pgo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/usr/bin/env bash
# PGO (Profile-Guided Optimization) build script for world-chain.
#
# This script automates the three-phase PGO workflow:
# 1. Build with PGO instrumentation
# 2. Collect profile data by running benchmarks
# 3. Rebuild with PGO optimization applied
#
# Environment variables:
# FEATURES - Cargo features (default: "jemalloc")
# PGO_DATA_DIR - Directory for raw PGO data (default: /tmp/pgo-data)
# EXTRA_RUSTFLAGS - Additional RUSTFLAGS (default: "")
# SKIP_COLLECT - Skip collection phase, use existing data (default: false)
# STRIP_SYMBOLS - Strip debug symbols from final binary (default: false)
#
# Usage:
# .github/scripts/build_pgo.sh

set -euo pipefail

FEATURES="${FEATURES:-jemalloc}"
PGO_DATA_DIR="${PGO_DATA_DIR:-/tmp/pgo-data}"
EXTRA_RUSTFLAGS="${EXTRA_RUSTFLAGS:-}"
SKIP_COLLECT="${SKIP_COLLECT:-false}"
STRIP_SYMBOLS="${STRIP_SYMBOLS:-false}"

BIN="world-chain"
PROFILE_BUILD="profiling"
PROFILE_FINAL="maxperf"

# Resolve llvm-profdata from the rustc sysroot
SYSROOT=$(rustc --print sysroot)
HOST_TRIPLE=$(rustc -vV | awk '/^host:/ { print $2 }')
LLVM_PROFDATA="$SYSROOT/lib/rustlib/$HOST_TRIPLE/bin/llvm-profdata"

if [[ ! -f "$LLVM_PROFDATA" ]]; then
echo "ERROR: llvm-profdata not found. Install llvm-tools-preview:"
echo " rustup component add llvm-tools-preview"
exit 1
fi

echo "=== Phase 1: PGO Instrumented Build ==="
mkdir -p "$PGO_DATA_DIR"

RUSTFLAGS="-Cprofile-generate=$PGO_DATA_DIR -C target-cpu=native $EXTRA_RUSTFLAGS" \
cargo build --profile "$PROFILE_BUILD" --features "$FEATURES" --bin "$BIN"

echo "Instrumented binary: target/$PROFILE_BUILD/$BIN"

if [[ "$SKIP_COLLECT" != "true" ]]; then
echo ""
echo "=== Phase 2: Collect PGO Data ==="
echo "Running benchmarks to collect profile data..."

RUSTFLAGS="-Cprofile-generate=$PGO_DATA_DIR -C target-cpu=native $EXTRA_RUSTFLAGS" \
cargo bench --profile "$PROFILE_BUILD" \
--package world-chain-builder \
--bench coordinator \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no coordinator bench

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are:

help: available bench targets:
    flashblock_building_live_node
    flashblock_validation_live_node
    flashblock_validation_synthetic

What was previuously called coordinator is now called flashblock_validation_synthetic

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest live node benches though as they are more reliable and mimic more closely mainnet behaviours

-- --warm-up-time 3 --measurement-time 20

echo "Profile data collected in: $PGO_DATA_DIR"
echo "Files: $(find "$PGO_DATA_DIR" -name '*.profraw' | wc -l) .profraw files"
fi

echo ""
echo "=== Phase 3: Merge Profile Data ==="
"$LLVM_PROFDATA" merge -o "$PGO_DATA_DIR/merged.profdata" "$PGO_DATA_DIR"
echo "Merged profile: $PGO_DATA_DIR/merged.profdata"

echo ""
echo "=== Phase 4: PGO Optimized Build ==="
RUSTFLAGS="-Cprofile-use=$PGO_DATA_DIR/merged.profdata -C target-cpu=native $EXTRA_RUSTFLAGS" \
cargo build --profile "$PROFILE_FINAL" --features "$FEATURES" --bin "$BIN"

if [[ "$STRIP_SYMBOLS" == "true" ]]; then
echo "Stripping debug symbols..."
strip "target/$PROFILE_FINAL/$BIN"
fi

echo ""
echo "=== Done ==="
echo "PGO-optimized binary: target/$PROFILE_FINAL/$BIN"
SIZE=$(ls -lh "target/$PROFILE_FINAL/$BIN" | awk '{print $5}')
echo "Binary size: $SIZE"
159 changes: 159 additions & 0 deletions .github/workflows/profiling.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
name: Profiling Build

on:
workflow_dispatch:
inputs:
profile:
description: 'Cargo profile to build with'
required: true
default: 'profiling'
type: choice
options:
- profiling
- maxperf
enable_pgo:
description: 'Enable PGO data collection and optimized rebuild'
required: false
default: false
type: boolean
workflow_call:
inputs:
profile:
required: true
type: string
default: 'profiling'
enable_pgo:
required: false
type: boolean
default: false

env:
CARGO_TERM_COLOR: always

permissions:
contents: read

jobs:
build-profiling:
name: Build (${{ inputs.profile }})
runs-on: arc-public-8xlarge-amd64-runner
timeout-minutes: 120
env:
PROFILE: ${{ inputs.profile }}
steps:
- uses: actions/checkout@v6

- uses: dtolnay/rust-toolchain@stable

- name: Cache
uses: actions/cache@v5
continue-on-error: false
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: cargo-profiling-${{ hashFiles('**/Cargo.lock') }}
restore-keys: cargo-profiling-

- name: Build profiling binary
run: |
case "${PROFILE}" in
profiling|maxperf) ;;
*) echo "invalid profile: ${PROFILE}" >&2; exit 1 ;;
esac

RUSTFLAGS="-C target-cpu=native" \
cargo build --profile "${PROFILE}" \
--features jemalloc \
--bin world-chain

Comment thread
0xOsiris marked this conversation as resolved.
Comment thread
0xOsiris marked this conversation as resolved.
- name: Upload profiling binary
uses: actions/upload-artifact@v7
with:
name: world-chain-${{ env.PROFILE }}-x86_64-linux
path: target/${{ env.PROFILE }}/world-chain
retention-days: 7

build-pgo:
name: PGO Build
if: ${{ inputs.enable_pgo }}
runs-on: arc-public-8xlarge-amd64-runner
timeout-minutes: 180
steps:
- uses: actions/checkout@v6

- uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview

- name: Cache
uses: actions/cache@v5
continue-on-error: false
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
key: cargo-pgo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: cargo-pgo-

- name: Phase 1 - PGO instrumented build
run: |
just build-pgo-instrumented

- name: Phase 2 - Collect PGO data via benchmarks
run: |
RUSTFLAGS="-Cprofile-generate=/tmp/pgo-data -C target-cpu=native" \
cargo bench --profile profiling \
--package world-chain-builder \
--bench coordinator \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

-- --warm-up-time 5 --measurement-time 30

- name: Phase 3 - Merge PGO profile data
run: |
just merge-pgo

- name: Phase 4 - PGO optimized build
run: |
just build-pgo-optimized

- name: Upload PGO-optimized binary
uses: actions/upload-artifact@v7
with:
name: world-chain-pgo-optimized-x86_64-linux
path: target/maxperf/world-chain
retention-days: 7

- name: Upload PGO profile data
uses: actions/upload-artifact@v7
with:
name: pgo-profile-data
path: /tmp/pgo-data/merged.profdata
retention-days: 1

docker-profiling:
name: Docker profiling image
needs: build-profiling
runs-on: arc-public-8xlarge-amd64-runner
timeout-minutes: 90
steps:
- uses: actions/checkout@v6

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build profiling Docker image
run: |
just docker-profiling

- name: Save Docker image
run: |
docker save world-chain:profiling | gzip > world-chain-profiling.tar.gz

- name: Upload Docker image
uses: actions/upload-artifact@v7
with:
name: world-chain-docker-profiling
path: world-chain-profiling.tar.gz
retention-days: 3
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ inherits = "dev"
[profile.verbose-tracing]
inherits = "dev"

[profile.profiling]
inherits = "release"
debug = "full"
strip = "none"

[workspace.lints]

Expand Down
54 changes: 54 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,57 @@ docs:

install *args='':
cargo install --path bin/world-chain --locked $@

# === Profiling ===

# Build with profiling profile (release + debug symbols for perf/samply/flamegraph)
build-profiling features='jemalloc':
RUSTFLAGS="-C target-cpu=native" cargo build --profile profiling --features {{ features }} --bin world-chain

# Build with maxperf profile + native CPU targeting
build-maxperf features='jemalloc':
RUSTFLAGS="-C target-cpu=native" cargo build --profile maxperf --features {{ features }} --bin world-chain

# Build release targeting native CPU (without profiling symbols)
build-native features='jemalloc':
RUSTFLAGS="-C target-cpu=native" cargo build --release --features {{ features }} --bin world-chain

# Run benchmarks with profiling profile
bench-profiling *args='':
RUSTFLAGS="-C target-cpu=native" cargo bench --profile profiling --package world-chain-builder --bench coordinator -- $@

# Run playground with profiling build for profile data collection
stress-profile *args='':
RUSTFLAGS="-C target-cpu=native" RUST_LOG="info" cargo run -p xtask --profile profiling -- launch-node --nodes 2 --spam --num-blocks 100 $@

# Build Docker image with profiling profile
docker-profiling features='jemalloc':
docker buildx build \
--build-arg PROFILE=profiling \
--build-arg FEATURES={{ features }} \
-t world-chain:profiling .

# Build Docker image with maxperf profile
docker-maxperf features='jemalloc':
docker buildx build \
--build-arg PROFILE=maxperf \
--build-arg FEATURES={{ features }} \
-t world-chain:maxperf .

# === PGO (Profile-Guided Optimization) ===

# PGO phase 1: build with instrumentation
build-pgo-instrumented pgo_data_dir='/tmp/pgo-data' features='jemalloc':
mkdir -p {{ pgo_data_dir }}
RUSTFLAGS="-Cprofile-generate={{ pgo_data_dir }} -C target-cpu=native" \
cargo build --profile profiling --features {{ features }} --bin world-chain

# Merge PGO profile data files into a single .profdata
merge-pgo pgo_data_dir='/tmp/pgo-data':
$(rustc --print sysroot)/lib/rustlib/$(rustc -vV | awk '/^host:/ { print $2 }')/bin/llvm-profdata \
merge -o {{ pgo_data_dir }}/merged.profdata {{ pgo_data_dir }}

# PGO phase 3: build with optimization using collected profile data
build-pgo-optimized pgo_merged='/tmp/pgo-data/merged.profdata' features='jemalloc':
RUSTFLAGS="-Cprofile-use={{ pgo_merged }} -C target-cpu=native" \
cargo build --profile maxperf --features {{ features }} --bin world-chain
Loading