From 7f8bdb09de2230d7f44efa6f874e7dde1bd3b036 Mon Sep 17 00:00:00 2001 From: Yuansheng Date: Fri, 14 Aug 2026 06:36:31 +0800 Subject: [PATCH 1/2] build: add thin-LTO release-dev profile for iteration builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The release profile's fat LTO + codegen-units=1 serializes the whole LTO stage onto one core: a cold build of the aisix binary takes 6m37s wall on a 12-core host. PGO retraining pays this twice per cycle, because the changed RUSTFLAGS invalidates every fingerprint, so the instrumented and optimized builds are both full rebuilds. Add a release-dev profile inheriting release, with lto = "thin" and codegen-units = 16, so the LTO stage parallelizes: the same cold build finishes in 2m27s at 914% average CPU on the same host (2.7x faster). The profile comment pins the discipline: functionally identical output, slightly less optimized — any number that is reported, compared against a baseline, or fed into the saturation grid must come from --release, never from release-dev. --- Cargo.toml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 777723e3..2af18eb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -205,6 +205,17 @@ lto = "fat" codegen-units = 1 strip = "debuginfo" +# Iteration-speed sibling of `release`: thin LTO parallelizes the LTO +# stage across cores instead of fat LTO's single-threaded whole-graph +# pass, cutting link-heavy rebuilds from minutes to tens of seconds. +# Functionally identical output, slightly less optimized — so any number +# that gets reported, compared against a baseline, or fed into the +# saturation grid MUST come from `--release`, never from this profile. +[profile.release-dev] +inherits = "release" +lto = "thin" +codegen-units = 16 + [profile.coverage] inherits = "dev" opt-level = 0 From 6a42d78c4116c2c00269579d757bf25330e9b18b Mon Sep 17 00:00:00 2001 From: Yuansheng Date: Fri, 14 Aug 2026 06:42:39 +0800 Subject: [PATCH 2/2] bench: rebuild the release binary inside the run scripts' sanity gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review of #976 flagged that run-baseline.sh and run-decay.sh trust target/release/aisix to be fresh: the only check was the executable bit. That held while iteration and measurement builds shared the release profile; with release-dev absorbing iteration builds, a stale release binary becomes a silent way to publish numbers for the wrong commit. Rebuild in the sanity section instead — a no-op when the binary is already current — and fail loudly if the build cannot run. Also reword the release-dev comment to claim only what was measured (cold builds: 6m37s fat vs 2m27s thin) instead of an unmeasured incremental-rebuild figure. --- Cargo.toml | 9 +++++---- bench/onthebench/run-baseline.sh | 7 ++++++- bench/onthebench/run-decay.sh | 5 ++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2af18eb5..3c5e5c46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -207,10 +207,11 @@ strip = "debuginfo" # Iteration-speed sibling of `release`: thin LTO parallelizes the LTO # stage across cores instead of fat LTO's single-threaded whole-graph -# pass, cutting link-heavy rebuilds from minutes to tens of seconds. -# Functionally identical output, slightly less optimized — so any number -# that gets reported, compared against a baseline, or fed into the -# saturation grid MUST come from `--release`, never from this profile. +# pass — measured cold builds of the aisix binary on a 12-core host: +# 6m37s (release) vs 2m27s (release-dev). Functionally identical output, +# slightly less optimized — so any number that gets reported, compared +# against a baseline, or fed into the saturation grid MUST come from +# `--release`, never from this profile. [profile.release-dev] inherits = "release" lto = "thin" diff --git a/bench/onthebench/run-baseline.sh b/bench/onthebench/run-baseline.sh index 53283789..8b136aef 100755 --- a/bench/onthebench/run-baseline.sh +++ b/bench/onthebench/run-baseline.sh @@ -27,7 +27,12 @@ BIN="$SRC/target/release/aisix" # ---- sanity ----------------------------------------------------------------- -[ -x "$BIN" ] || { echo "FATAL: $BIN missing - build first"; exit 1; } +# Rebuild instead of trusting mtime: with iteration builds living in +# target/release-dev, a stale target/release binary is silent poison — +# meta.json would attribute the numbers to the wrong commit. A no-op +# when the binary is already current. +( cd "$SRC" && cargo build --locked --release --bin aisix ) +[ -x "$BIN" ] || { echo "FATAL: $BIN missing after build"; exit 1; } rig_sanity if [ "$FLAMEGRAPH" = 1 ]; then require_symbols "$BIN"; fi diff --git a/bench/onthebench/run-decay.sh b/bench/onthebench/run-decay.sh index 60244f39..b4b8c776 100755 --- a/bench/onthebench/run-decay.sh +++ b/bench/onthebench/run-decay.sh @@ -56,7 +56,10 @@ BIN="$SRC/target/release/aisix" # ---- sanity ----------------------------------------------------------------- -[ -x "$BIN" ] || { echo "FATAL: $BIN missing - build first"; exit 1; } +# Rebuild instead of trusting mtime — same stale-binary gate as +# run-baseline.sh; a no-op when the binary is already current. +( cd "$SRC" && cargo build --locked --release --bin aisix ) +[ -x "$BIN" ] || { echo "FATAL: $BIN missing after build"; exit 1; } rig_sanity bench_init