Skip to content
Merged
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
4 changes: 4 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ CI/CD workflows for the fbuild project, covering lint, test, documentation, and
- **`loc-gate.yml`** -- Reject `.rs` files over 1000 LOC | **`lint-subprocess.yml`** -- Forbid direct subprocess spawns
- **`crate-gate.yml`** -- Reject new workspace crates (monocrate policy, `ci/check_workspace_crates.py`)

## Scheduled Benchmarks

- **`benchmark-build-comparison.yml`** -- Arduino CLI vs PlatformIO vs fbuild Blink cold/warm benchmark; runs nightly, manually, and for relevant pushes to `main`, then force-publishes the one-commit `benchmark-stats` branch and deploys its site to GitHub Pages

## Per-Board Builds (push/PR)

- **`build-esp32{c2,c3,c5,c6,dev,h2,p4,s2,s3}.yml`** -- ESP32 variants
Expand Down
195 changes: 195 additions & 0 deletions .github/workflows/benchmark-build-comparison.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
name: Build Comparison Benchmark

on:
workflow_dispatch:
push:
branches: [main]
paths:
- 'bench/blink/**'
- 'bench/fastled-examples/src/build_comparison.rs'
- 'bench/fastled-examples/Cargo.toml'
- '.github/workflows/benchmark-build-comparison.yml'
schedule:
# Off-hour UTC slot avoids the hosted-runner top-of-hour surge.
- cron: '17 9 * * *'

concurrency:
group: benchmark-build-comparison-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

env:
CARGO_TERM_COLOR: always
RUSTFLAGS: '-D warnings'
PLATFORMIO_CORE_VERSION: '6.1.19'
ARDUINO_CLI_VERSION: '1.5.0'
ARDUINO_AVR_CORE_VERSION: '1.8.8'

jobs:
benchmark:
name: Measure and publish Blink builds
runs-on: ubuntu-24.04
timeout-minutes: 60
steps:
- uses: actions/checkout@v6
Comment thread
coderabbitai[bot] marked this conversation as resolved.
with:
persist-credentials: false

- uses: astral-sh/setup-uv@v3

- name: Setup soldr
uses: zackees/setup-soldr@v0
with:
version: 0.8.8
cache: true
build-cache: true
target-cache: true
prebuild-deps: none
linker: platform-default
cache-payload-warn-bytes: 2GiB

- name: Install Arduino CLI
uses: arduino/setup-arduino-cli@v2
with:
version: ${{ env.ARDUINO_CLI_VERSION }}

- name: Install benchmark toolchains
shell: bash
run: |
set -euo pipefail
uv tool install "platformio==${PLATFORMIO_CORE_VERSION}"
arduino-cli core update-index
arduino-cli core install "arduino:avr@${ARDUINO_AVR_CORE_VERSION}"
pio pkg install --project-dir bench/blink --environment uno

- name: Build fbuild and benchmark runner
shell: bash
run: |
set -euo pipefail
soldr cargo build --release \
-p fbuild-cli --bin fbuild \
-p fbuild-daemon --bin fbuild-daemon \
-p fbuild-bench-fastled-examples --bin bench-build-comparison

- name: Prime package downloads outside timed measurements
shell: bash
run: |
set -euo pipefail
mkdir -p benchmark-output/bootstrap-arduino
arduino-cli compile \
--fqbn arduino:avr:uno \
--build-path benchmark-output/bootstrap-arduino \
bench/blink
target/release/fbuild build bench/blink -e uno --release
target/release/fbuild clean all bench/blink -e uno --release
rm -rf benchmark-output/bootstrap-arduino

- name: Restore rolling history
shell: bash
run: |
set -euo pipefail
mkdir -p benchmark-stats
if git ls-remote --exit-code origin refs/heads/benchmark-stats >/dev/null; then
git fetch --depth=1 origin refs/heads/benchmark-stats
git show FETCH_HEAD:history.jsonl > benchmark-stats/history.jsonl
else
status=$?
if [[ "${status}" -eq 2 ]]; then
: > benchmark-stats/history.jsonl
else
exit "${status}"
fi
fi

- name: Run cold/warm comparison and render site
shell: bash
run: |
set -euo pipefail
generated_at="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
target/release/bench-build-comparison \
--project-dir bench/blink \
--fbuild target/release/fbuild \
--output-dir benchmark-stats \
--trials 3 \
--repository "${GITHUB_REPOSITORY}" \
--git-sha "${GITHUB_SHA}" \
--generated-at "${generated_at}" \
--run-url "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \
--pages-url https://fastled.github.io/fbuild/ \
--raw-base-url https://github.com/ghraw/FastLED/fbuild/benchmark-stats

- name: Upload benchmark site snapshot
uses: actions/upload-artifact@v7
with:
name: build-comparison-site-${{ github.sha }}
path: benchmark-stats
include-hidden-files: true
if-no-files-found: error
retention-days: 30

- name: Upload benchmark log
if: always()
uses: actions/upload-artifact@v7
with:
name: build-comparison-log-${{ github.sha }}
path: benchmark-output/benchmark.log
if-no-files-found: warn
retention-days: 30

publish:
name: Publish benchmark artifacts
needs: benchmark
if: ${{ needs.benchmark.result == 'success' && github.ref == 'refs/heads/main' }}
runs-on: ubuntu-24.04
permissions:
contents: write
pages: write
Comment thread
coderabbitai[bot] marked this conversation as resolved.
steps:
- name: Download benchmark site snapshot
uses: actions/download-artifact@v8
with:
name: build-comparison-site-${{ github.sha }}
path: benchmark-stats

- name: Publish one-commit benchmark-stats branch
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
publish_dir="$(mktemp -d)"
cp -a benchmark-stats/. "${publish_dir}/"
git -C "${publish_dir}" init
git -C "${publish_dir}" checkout -b benchmark-stats
git -C "${publish_dir}" config user.name 'github-actions[bot]'
git -C "${publish_dir}" config user.email '41898282+github-actions[bot]@users.noreply.github.com'
git -C "${publish_dir}" add .
git -C "${publish_dir}" commit -m "chore: publish build benchmark for ${GITHUB_SHA}"
git -C "${publish_dir}" remote add origin \
"https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
git -C "${publish_dir}" push --force origin benchmark-stats

- name: Configure GitHub Pages
uses: actions/configure-pages@v5

- name: Upload GitHub Pages artifact
uses: actions/upload-pages-artifact@v4
with:
path: benchmark-stats

deploy-pages:
name: Deploy benchmark report
needs: publish
runs-on: ubuntu-24.04
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
permissions:
pages: write
id-token: write
steps:
- name: Deploy GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ libiconv-2.dll

# fbuild local build artifacts
.fbuild/
.pio/
benchmark-output/
benchmark-stats/
tests/platform/*/build_info*.json

# Local cargo cache
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ that fbuild actively protects in CI.
Board descriptions and family deep-dives live in
[`docs/BOARD_STATUS.md`](docs/BOARD_STATUS.md).

## Build performance

[![Arduino CLI vs PlatformIO vs fbuild Blink build benchmark](https://github.com/ghraw/FastLED/fbuild/benchmark-stats/benchmark.svg)](https://fastled.github.io/fbuild/)

The chart is regenerated nightly from clean-output (cold) and immediate repeat
(warm) Arduino Uno Blink builds. Raw measurements are discoverable through the
[benchmark manifest](https://github.com/ghraw/FastLED/fbuild/benchmark-stats/manifest.json).

## Installation

```bash
Expand Down
6 changes: 6 additions & 0 deletions bench/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ soldr cargo bench -p fbuild-header-scan --bench scan_throughput

## Subdirectories

- [`blink/`](blink/README.md) — shared Arduino Uno Blink fixture used by the
nightly Arduino CLI vs PlatformIO vs fbuild whole-build benchmark.
- [`fastled-examples/`](fastled-examples/README.md) — real-FastLED
warm-cache library-selection matrix (`FastLED/fbuild#205` AC#5, P-01).
Discovers examples under `$FASTLED_DIR` (default `~/dev/fastled`),
Expand All @@ -31,3 +33,7 @@ Other end-to-end matrices (whole-build wall-clock, deploy+flash latency,
emulator boot) may join this directory in the future. Each subdirectory
must carry its own `README.md` explaining what it measures, how to run it,
and which CI gate (if any) it feeds.

The nightly whole-build comparison is published at
<https://fastled.github.io/fbuild/>. Its machine-readable discovery document
is `manifest.json` on the one-commit `benchmark-stats` branch.
49 changes: 49 additions & 0 deletions bench/blink/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Blink build comparison

This directory is one shared Arduino Uno Blink sketch for the nightly
whole-build comparison. Arduino CLI, PlatformIO, and fbuild compile the exact
same `blink.ino` file for the Arduino Uno target. Each ecosystem's framework
distribution is pinned independently: `arduino:avr@1.8.8` for Arduino CLI and
`atmelavr@5.1.0` for PlatformIO/fbuild.

Each tool is measured for three trials by default:

- **Cold** removes project outputs and matching compiled framework caches before
compiling. Installed toolchains/framework packages and global
download/compiler caches remain available.
- **Warm** immediately repeats the same build without changing any input.

The Rust runner records every trial and publishes the median. Cold bars are
drawn behind narrower warm overlays using the same GitHub-dark gray, blue, and
red palette as the zccache and soldr benchmark graphics.

## Run locally

Install Arduino CLI, its `arduino:avr` core, and PlatformIO first. Build fbuild
and run the harness through `soldr`:

```bash
soldr cargo build --release -p fbuild-cli --bin fbuild -p fbuild-daemon --bin fbuild-daemon
soldr cargo run --release -p fbuild-bench-fastled-examples \
--bin bench-build-comparison -- \
--project-dir bench/blink \
--fbuild target/release/fbuild \
--output-dir benchmark-stats
```

The `target/release/fbuild` path above is for Linux and CI. On Windows, use
`target/x86_64-pc-windows-msvc/release/fbuild.exe`.

The nightly workflow installs and records pinned Arduino CLI and PlatformIO
versions, primes package downloads outside the timed region, carries forward a
365-run `history.jsonl`, and publishes:

- `manifest.json` — stable discovery index for agents and other clients
- `latest.json` — full metadata, raw trials, and medians for the newest run
- `history.jsonl` — rolling compact history
- `benchmark.svg` — README graphic with cold/warm overlays
- `index.html` — human-facing GitHub Pages report

The `benchmark-stats` branch is force-published from a fresh repository on
every successful default-branch run, so its Git history always contains one
generated commit.
10 changes: 10 additions & 0 deletions bench/blink/blink.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
}
7 changes: 7 additions & 0 deletions bench/blink/platformio.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[platformio]
src_dir = .

[env:uno]
platform = atmelavr@5.1.0
board = uno
framework = arduino
Comment thread
coderabbitai[bot] marked this conversation as resolved.
7 changes: 6 additions & 1 deletion bench/fastled-examples/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fbuild-bench-fastled-examples"
description = "Warm-cache library-selection bench across the FastLED examples matrix (#205 Phase 7)"
description = "End-to-end benchmark harnesses for fbuild"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
Expand All @@ -11,10 +11,15 @@ publish = false
name = "bench-fastled-examples"
path = "src/main.rs"

[[bin]]
name = "bench-build-comparison"
path = "src/build_comparison.rs"

[dependencies]
fbuild-library-select = { path = "../../crates/fbuild-library-select" }
fbuild-packages = { path = "../../crates/fbuild-packages" }
fbuild-paths = { path = "../../crates/fbuild-paths" }
fbuild-test-support = { path = "../../crates/fbuild-test-support" }
tempfile = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
10 changes: 8 additions & 2 deletions bench/fastled-examples/src/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# bench/fastled-examples/src

Source for the `bench-fastled-examples` binary. See the parent
[`README.md`](../README.md) for what the harness does and how to run it.
Sources for the repository's end-to-end benchmark binaries:

- `main.rs` implements `bench-fastled-examples`.
- `build_comparison.rs` implements the nightly Arduino CLI vs PlatformIO vs
fbuild Blink build comparison and static-site renderer.

See the parent [`README.md`](../README.md) for the FastLED harness and
[`../../blink/README.md`](../../blink/README.md) for the whole-build benchmark.
Loading
Loading