From 5c4105a5c7c884db207cadfd71a91cf1e608a9a7 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas-Claude Date: Fri, 11 Sep 2026 11:43:51 -0400 Subject: [PATCH] Add AirspeedVelocity benchmarking CI Adds a benchmark workflow (Julia 1 and lts) and a benchmark/benchmarks.jl suite covering representative workloads so PRs check for performance regressions. Co-Authored-By: Chris Rackauckas Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> Agent-Harness: devin 3000.10.21 (611c1cba) Agent-Model: SWE-2 High Agent-Session: local session transcript /home/crackauc/sandbox/tmp_20260911_112052_59120/history_6a789c0b69c64ca3.md --- .github/workflows/benchmark.yml | 29 +++++++++++++++++++ benchmark/benchmarks.jl | 50 +++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 .github/workflows/benchmark.yml create mode 100644 benchmark/benchmarks.jl diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 00000000..b35da5d5 --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,29 @@ +name: Benchmark this PR + +on: + pull_request: + branches: [master] + paths-ignore: ['docs/**'] + +permissions: + pull-requests: write + contents: read + +jobs: + benchmark: + runs-on: ubuntu-latest + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + version: ["1", "lts"] + env: + # Force consistent Julia depot path for self-hosted runners + JULIA_DEPOT_PATH: ~/.julia + steps: + - uses: MilesCranmer/AirspeedVelocity.jl@action-v1 + with: + julia-version: ${{ matrix.version }} + script: "benchmark/benchmarks.jl" + extra-pkgs: "StableRNGs" + job-summary: true diff --git a/benchmark/benchmarks.jl b/benchmark/benchmarks.jl new file mode 100644 index 00000000..2e75bb48 --- /dev/null +++ b/benchmark/benchmarks.jl @@ -0,0 +1,50 @@ +using RecursiveArrayTools, BenchmarkTools +using LinearAlgebra, StableRNGs + +const SUITE = BenchmarkGroup() +const rng = StableRNG(123) + +# ============================================================================= +# ArrayPartition +# ============================================================================= + +SUITE["arraypartition"] = BenchmarkGroup() + +ap1 = ArrayPartition(rand(rng, 500), rand(rng, 40, 40), rand(rng, 60)) +ap2 = ArrayPartition(rand(rng, 500), rand(rng, 40, 40), rand(rng, 60)) + +SUITE["arraypartition"]["construct"] = @benchmarkable ArrayPartition( + $(rand(rng, 500)), $(rand(rng, 40, 40)), $(rand(rng, 60)) +) +SUITE["arraypartition"]["broadcast_add"] = @benchmarkable $ap1 .+ $ap2 +SUITE["arraypartition"]["scalar_mul"] = @benchmarkable 1.5 .* $ap1 +SUITE["arraypartition"]["norm"] = @benchmarkable norm($ap1) +SUITE["arraypartition"]["recursivecopy!"] = @benchmarkable recursivecopy!( + out, $ap1 +) setup = (out = recursivecopy($ap1)) +SUITE["arraypartition"]["recursivefill!"] = @benchmarkable recursivefill!( + out, 0.5 +) setup = (out = recursivecopy($ap1)) + +# ============================================================================= +# VectorOfArray +# ============================================================================= + +SUITE["vectorofarray"] = BenchmarkGroup() + +voa_u = [rand(rng, 200) for i in 1:100] +voa = VectorOfArray(voa_u) +voa2 = VectorOfArray([rand(rng, 200) for i in 1:100]) + +SUITE["vectorofarray"]["construct"] = @benchmarkable VectorOfArray($voa_u) +SUITE["vectorofarray"]["to_matrix"] = @benchmarkable Array($voa) +SUITE["vectorofarray"]["broadcast_add"] = @benchmarkable $voa .+ $voa2 +SUITE["vectorofarray"]["map"] = @benchmarkable vecvecapply(sum, $voa) + +# ============================================================================= +# Nested broadcast (mixed ArrayPartition in VectorOfArray) +# ============================================================================= + +SUITE["nested"] = BenchmarkGroup() +nested = VectorOfArray([ArrayPartition(rand(rng, 20), rand(rng, 10)) for i in 1:50]) +SUITE["nested"]["broadcast_add"] = @benchmarkable $nested .+ $nested