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
154 changes: 151 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ on:
pull_request:
branches: [main, develop]
schedule:
# Nightly property tests
- cron: '23 4 * * *'
# Weekly gas baseline rotation (Mondays 05:17 UTC)
- cron: '17 5 * * 1'

jobs:
changes:
Expand Down Expand Up @@ -177,7 +180,7 @@ jobs:
working-directory: stellar/stealth-registry

stellar-nightly:
if: github.event_name == 'schedule'
if: github.event_name == 'schedule' && github.event.schedule == '23 4 * * *'
runs-on: ubuntu-latest
defaults:
run:
Expand All @@ -192,7 +195,7 @@ jobs:
- run: WRAITH_PROPTEST_CASES=16384 cargo test --workspace --test properties

stellar-deploy-dryrun:
if: github.event_name == 'schedule'
if: github.event_name == 'schedule' && github.event.schedule == '23 4 * * *'
runs-on: ubuntu-latest
defaults:
run:
Expand Down Expand Up @@ -249,7 +252,7 @@ jobs:
stellar/contract-ids.txt

stellar-chaos-nightly:
if: github.event_name == 'schedule'
if: github.event_name == 'schedule' && github.event.schedule == '23 4 * * *'
runs-on: ubuntu-latest
defaults:
run:
Expand All @@ -263,6 +266,151 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- name: Run chaos integration tests
run: cargo test --package integration-tests -- --nocapture

# Run benches on develop, upload results artifact, auto-update PERF.md.
# Note: cargo bench runs with CWD = package dir (stellar/bench/), so --out
# paths are relative to stellar/bench/ (e.g. results.json -> stellar/bench/results.json).
stellar-bench-develop:
if: github.event_name == 'push' && github.ref == 'refs/heads/develop'
runs-on: ubuntu-latest
permissions:
contents: write
defaults:
run:
working-directory: stellar
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}

- uses: dtolnay/rust-toolchain@stable

- name: Run gas bench
env:
GITHUB_SHA: ${{ github.sha }}
run: |
cargo bench -p wraith-stellar-bench --bench gas -- \
--format json --out results.json
test -f bench/results.json

- name: Upload bench results artifact
uses: actions/upload-artifact@v4
with:
name: stellar-bench-results
path: stellar/bench/results.json
retention-days: 90

- name: Update PERF.md current numbers
run: python3 bench/update_perf_md.py PERF.md bench/results.json

- name: Commit PERF.md if changed
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: 'chore(perf): auto-update Stellar PERF.md bench table'
file_pattern: stellar/PERF.md
commit_user_name: github-actions[bot]
commit_user_email: github-actions[bot]@users.noreply.github.com

# PR gate: fail when any per-op instructions exceed baseline + 5%.
stellar-bench-pr:
needs: changes
if: github.event_name == 'pull_request' && needs.changes.outputs.stellar == 'true'
runs-on: ubuntu-latest
defaults:
run:
working-directory: stellar
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable

- name: Download weekly baseline artifact
id: download-baseline
uses: dawidd6/action-download-artifact@v6
continue-on-error: true
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: ci.yml
branch: develop
name: stellar-bench-baseline
path: stellar/bench/artifact-baseline
search_artifacts: true
if_no_artifact_found: warn

- name: Resolve baseline path
id: baseline
run: |
if [ -f bench/artifact-baseline/baseline.json ]; then
echo "path=bench/artifact-baseline/baseline.json" >> "$GITHUB_OUTPUT"
echo "Using weekly-rotated artifact baseline"
else
echo "path=bench/baseline.json" >> "$GITHUB_OUTPUT"
echo "Using committed bench/baseline.json fallback"
fi

- name: Run gas bench
env:
GITHUB_SHA: ${{ github.sha }}
run: |
cargo bench -p wraith-stellar-bench --bench gas -- \
--format json --out results.json
test -f bench/results.json

- name: Compare vs baseline (+5% instructions gate)
run: |
python3 bench/compare.py \
"${{ steps.baseline.outputs.path }}" \
bench/results.json \
--threshold-pct 5

- name: Upload PR bench results
if: always()
uses: actions/upload-artifact@v4
with:
name: stellar-bench-pr-${{ github.event.pull_request.number }}
path: stellar/bench/results.json
retention-days: 30

# Weekly baseline rotation to catch slow drift under the 5% PR gate.
stellar-bench-baseline-rotate:
if: github.event_name == 'schedule' && github.event.schedule == '17 5 * * 1'
runs-on: ubuntu-latest
permissions:
contents: write
defaults:
run:
working-directory: stellar
steps:
- uses: actions/checkout@v4
with:
ref: develop
token: ${{ secrets.GITHUB_TOKEN }}

- uses: dtolnay/rust-toolchain@stable

- name: Run gas bench (rotate baseline)
env:
GITHUB_SHA: ${{ github.sha }}
run: |
cargo bench -p wraith-stellar-bench --bench gas -- \
--format json --out baseline.json
test -f bench/baseline.json

- name: Upload rotated baseline artifact
uses: actions/upload-artifact@v4
with:
name: stellar-bench-baseline
path: stellar/bench/baseline.json
retention-days: 90

- name: Commit rotated baseline.json
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: 'chore(perf): rotate Stellar gas bench baseline'
file_pattern: stellar/bench/baseline.json
commit_user_name: github-actions[bot]
commit_user_email: github-actions[bot]@users.noreply.github.com

solana:
needs: changes
if: needs.changes.outputs.solana == 'true'
Expand Down
11 changes: 11 additions & 0 deletions stellar/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,14 @@ debug = false
debug-assertions = false
overflow-checks = false
incremental = false

# Host-side benches (soroban-sdk testutils) cannot use the contract release
# profile: panic="abort" + LTO splits/breaks sdk type identity across crates.
[profile.bench]
inherits = "release"
lto = false
panic = "unwind"
codegen-units = 16
strip = false
debug = true
debug-assertions = true
19 changes: 17 additions & 2 deletions stellar/PERF.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Measured on 2026-06-01 with `soroban-sdk = 22.0.0` resolved to `22.0.11`.
The reusable harness is in `stellar/bench/` and can be re-run with:

```sh
cargo run -p wraith-stellar-bench
cargo bench -p wraith-stellar-bench --bench gas
# or: cargo run -p wraith-stellar-bench
```

## How to Read the Units
Expand Down Expand Up @@ -66,7 +67,8 @@ ownership checks.

## Current Numbers

These are the post-optimization harness results.
<!-- BENCH:CURRENT:START -->
These are the harness results auto-updated from `develop` (measured 2025-06-15, commit `seeded-from-`).

| Contract | Function | Parameters | Instructions | Mem bytes | Read entries | Write entries | Read bytes | Write bytes | Event bytes |
|---|---|---:|---:|---:|---:|---:|---:|---:|---:|
Expand All @@ -92,6 +94,19 @@ These are the post-optimization harness results.
| wraith-names | resolve | miss | 19766 | 1600 | 1 | 0 | 104 | 0 | 0 |
| wraith-names | name_of | hit | 47042 | 5383 | 1 | 0 | 452 | 0 | 0 |
| wraith-names | name_of | miss | 21581 | 1513 | 1 | 0 | 104 | 0 | 0 |
<!-- BENCH:CURRENT:END -->

## Gas Regression Gate

CI compares PR bench results against the weekly-rotated baseline in
`stellar/bench/baseline.json` (also published as the `stellar-bench-baseline`
workflow artifact). A PR fails when any per-op `instructions` exceeds
baseline + 5%. Re-run locally:

```sh
cargo bench -p wraith-stellar-bench --bench gas -- --format json --out /tmp/bench.json
python3 bench/compare.py bench/baseline.json /tmp/bench.json
```

## Batch vs Individual Crossover

Expand Down
3 changes: 3 additions & 0 deletions stellar/bench/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Local / CI bench outputs (never commit nested accidental paths)
results.json
bench/
12 changes: 8 additions & 4 deletions stellar/bench/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ edition = "2021"

[dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
stealth-announcer = { path = "../stealth-announcer" }
stealth-registry = { path = "../stealth-registry" }
stealth-sender = { path = "../stealth-sender" }
wraith-names = { path = "../wraith-names" }
stealth-announcer = { path = "../stealth-announcer", features = ["testutils"] }
stealth-registry = { path = "../stealth-registry", features = ["testutils"] }
stealth-sender = { path = "../stealth-sender", features = ["testutils"] }
wraith-names = { path = "../wraith-names", features = ["testutils"] }

[[bench]]
name = "gas"
harness = false
Loading
Loading