Skip to content

Commit 51db3b2

Browse files
connortsui20claude
andcommitted
refactor(ci): share Rust micro-benchmark workflow
Declare the two Rust micro-benchmark binaries in a small dedicated resolver and expose them through the existing matrix command. Replace the duplicated develop and PR jobs with one reusable workflow while preserving their mode-specific result handling. Keep this separate from the SQL profile migration so each change can be reviewed and landed independently. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
1 parent 80f1d97 commit 51db3b2

8 files changed

Lines changed: 307 additions & 257 deletions

File tree

.github/workflows/bench-core.yml

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
name: Rust micro-benchmarks
2+
3+
# Reusable workflow for the Rust micro-benchmarks (random access, compression). Called by bench.yml
4+
# (mode=develop) and bench-pr.yml (mode=pr). The matrix is resolved declaratively from
5+
# bench-orchestrator; see bench-orchestrator/bench_orchestrator/matrix.py.
6+
7+
on:
8+
workflow_call:
9+
inputs:
10+
mode:
11+
required: true
12+
type: string
13+
profile:
14+
required: false
15+
type: string
16+
default: "micro"
17+
18+
jobs:
19+
plan:
20+
runs-on: ubuntu-latest
21+
timeout-minutes: 10
22+
outputs:
23+
matrix: ${{ steps.resolve.outputs.matrix }}
24+
steps:
25+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
26+
if: inputs.mode == 'pr'
27+
with:
28+
ref: ${{ github.event.pull_request.head.sha }}
29+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
30+
if: inputs.mode != 'pr'
31+
- name: Install uv
32+
uses: spiraldb/actions/.github/actions/setup-uv@a746510eafaa926484c354541cfc49b2ec06cc63 # 0.18.6
33+
with:
34+
sync: false
35+
- name: Resolve benchmark matrix
36+
id: resolve
37+
shell: bash
38+
env:
39+
PROFILE: ${{ inputs.profile }}
40+
run: |
41+
echo "matrix=$(uv run --project bench-orchestrator vx-bench matrix "$PROFILE")" >> "$GITHUB_OUTPUT"
42+
43+
bench:
44+
needs: plan
45+
timeout-minutes: 120
46+
env:
47+
RUST_BACKTRACE: full
48+
VORTEX_EXPERIMENTAL_PATCHED_ARRAY: "1"
49+
FLAT_LAYOUT_INLINE_ARRAY_NODE: "1"
50+
strategy:
51+
fail-fast: false
52+
matrix:
53+
include: ${{ fromJSON(needs.plan.outputs.matrix) }}
54+
55+
runs-on: >-
56+
${{ github.repository == 'vortex-data/vortex'
57+
&& format('runs-on={0}/runner=bench-dedicated/tag={1}{2}', github.run_id, matrix.id, (inputs.mode != 'pr' || github.event.pull_request.head.repo.fork == false) && '/extras=s3-cache' || '')
58+
|| 'ubuntu-latest' }}
59+
steps:
60+
- uses: runs-on/action@v2
61+
if: inputs.mode != 'pr' || github.event.pull_request.head.repo.fork == false
62+
with:
63+
sccache: s3
64+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
65+
if: inputs.mode == 'pr'
66+
with:
67+
ref: ${{ github.event.pull_request.head.sha }}
68+
69+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
70+
if: inputs.mode != 'pr'
71+
- name: Setup benchmark environment
72+
run: sudo bash scripts/setup-benchmark.sh
73+
- uses: ./.github/actions/setup-rust
74+
with:
75+
repo-token: ${{ secrets.GITHUB_TOKEN }}
76+
enable-sccache: ${{ (inputs.mode != 'pr' || github.event.pull_request.head.repo.fork == false) && 'true' || 'false' }}
77+
- name: Install uv
78+
uses: spiraldb/actions/.github/actions/setup-uv@a746510eafaa926484c354541cfc49b2ec06cc63 # 0.18.6
79+
with:
80+
sync: false
81+
82+
- name: Install DuckDB
83+
run: |
84+
wget -qO- https://github.com/duckdb/duckdb/releases/download/v1.5.4/duckdb_cli-linux-amd64.zip | funzip > duckdb
85+
chmod +x duckdb
86+
echo "$PWD" >> "$GITHUB_PATH"
87+
88+
- uses: ./.github/actions/system-info
89+
90+
- name: Build binary
91+
shell: bash
92+
env:
93+
RUSTFLAGS: "-C target-cpu=native"
94+
run: |
95+
cargo build --bin ${{ matrix.id }} --profile release_debug ${{ matrix.build_args }} --features unstable_encodings
96+
97+
- name: Setup Polar Signals
98+
if: inputs.mode != 'pr' || github.event.pull_request.head.repo.fork == false
99+
uses: polarsignals/gh-actions-ps-profiling@68ae857e375a826606352016e5b90f01a2a7ff7a # v0.8.1
100+
with:
101+
polarsignals_cloud_token: ${{ secrets.POLAR_SIGNALS_API_KEY }}
102+
labels: "branch=${{ github.ref_name }};gh_run_id=${{ github.run_id }};benchmark=${{ matrix.id }}"
103+
project_uuid: "e5d846e1-b54c-46e7-9174-8bf055a3af56"
104+
profiling_frequency: 199
105+
extra_args: "--off-cpu-threshold=0.03" # Personally tuned by @brancz
106+
107+
- name: Run ${{ matrix.name }} benchmark (per-combination)
108+
if: ${{ matrix.split }}
109+
shell: bash
110+
run: |
111+
python3 scripts/random-access-split.py ${{ inputs.mode != 'pr' && '--v3' || '' }}
112+
113+
- name: Run ${{ matrix.name }} benchmark
114+
if: ${{ !matrix.split }}
115+
shell: bash
116+
run: |
117+
bash scripts/bench-taskset.sh target/release_debug/${{ matrix.id }} \
118+
--formats ${{ matrix.formats }} \
119+
-d gh-json \
120+
-o results.json \
121+
${{ inputs.mode != 'pr' && '--gh-json-v3 results.v3.jsonl' || '' }}
122+
123+
- name: Setup AWS CLI
124+
if: inputs.mode != 'pr' || github.event.pull_request.head.repo.fork == false
125+
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6
126+
with:
127+
role-to-assume: arn:aws:iam::245040174862:role/GitHubBenchmarkRole
128+
aws-region: us-east-1
129+
130+
- name: Compare results
131+
if: inputs.mode == 'pr'
132+
shell: bash
133+
run: |
134+
set -Eeu -o pipefail -x
135+
136+
python3 scripts/s3-download.py s3://vortex-ci-benchmark-results/data.json.gz data.json.gz --no-sign-request
137+
gzip -d -c data.json.gz > base.json
138+
139+
echo "# Benchmarks: ${{ matrix.name }}" > comment.md
140+
echo '' >> comment.md
141+
uv run --no-project scripts/compare-benchmark-jsons.py base.json results.json "${{ matrix.name }}" \
142+
>> comment.md
143+
cat comment.md >> "$GITHUB_STEP_SUMMARY"
144+
145+
- name: Comment PR
146+
if: inputs.mode == 'pr' && github.event.pull_request.head.repo.fork == false
147+
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3
148+
with:
149+
file-path: comment.md
150+
comment-tag: bench-pr-comment-${{ matrix.id }}
151+
152+
- name: Comment PR on failure
153+
if: failure() && inputs.mode == 'pr' && github.event.pull_request.head.repo.fork == false
154+
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3
155+
with:
156+
message: |
157+
# BENCHMARK FAILED
158+
159+
Benchmark `${{ matrix.name }}` failed! Check the [workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.
160+
comment-tag: bench-pr-comment-${{ matrix.id }}
161+
162+
- name: Upload Benchmark Results
163+
if: inputs.mode == 'develop'
164+
shell: bash
165+
run: |
166+
bash scripts/cat-s3.sh vortex-ci-benchmark-results data.json.gz results.json
167+
168+
# v4 (Postgres) ingest -- the REQUIRED benchmark-results pipeline feeding the live benchmarks
169+
# website (see bench.yml for the full rationale). Gated on inputs.mode == 'develop' + the
170+
# ingest-role ARN var. post-ingest.py mints the RDS IAM token (boto3) from the assumed
171+
# GitHubBenchmarkIngestRole; sslmode=verify-full validates the cert.
172+
- name: Configure AWS credentials for v4 ingest (OIDC)
173+
if: inputs.mode == 'develop' && vars.GH_BENCH_INGEST_ROLE_ARN != ''
174+
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6
175+
with:
176+
role-to-assume: ${{ vars.GH_BENCH_INGEST_ROLE_ARN }}
177+
aws-region: ${{ vars.RDS_BENCH_REGION }}
178+
- name: Ingest results to v4 Postgres
179+
if: inputs.mode == 'develop' && vars.GH_BENCH_INGEST_ROLE_ARN != ''
180+
shell: bash
181+
env:
182+
RDS_BENCH_INSTANCE_ENDPOINT: ${{ vars.RDS_BENCH_INSTANCE_ENDPOINT }}
183+
RDS_BENCH_DB_NAME: ${{ vars.RDS_BENCH_DB_NAME }}
184+
AWS_REGION: ${{ vars.RDS_BENCH_REGION }}
185+
BENCH_SITE_BASE_URL: ${{ vars.BENCH_SITE_BASE_URL }}
186+
BENCH_REVALIDATE_TOKEN: ${{ secrets.BENCH_REVALIDATE_TOKEN }}
187+
run: |
188+
set -Eeuo pipefail
189+
curl -fsSL https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem \
190+
-o "${RUNNER_TEMP}/rds-global-bundle.pem"
191+
DSN="postgresql://bench_ingest@${RDS_BENCH_INSTANCE_ENDPOINT}:5432/${RDS_BENCH_DB_NAME}?sslmode=verify-full&sslrootcert=${RUNNER_TEMP}/rds-global-bundle.pem"
192+
uv run --no-project --with 'psycopg[binary]' --with boto3 --with xxhash \
193+
scripts/post-ingest.py results.v3.jsonl \
194+
--postgres "${DSN}" \
195+
--commit-sha "${{ github.sha }}" \
196+
--region "${AWS_REGION}"
197+
198+
- name: Alert incident.io
199+
if: failure() && inputs.mode == 'develop'
200+
uses: ./.github/actions/alert-incident-io
201+
with:
202+
api-key: ${{ secrets.INCIDENT_IO_ALERT_TOKEN }}
203+
alert-title: "${{ matrix.name }} benchmark failed on develop"
204+
deduplication-key: ci-bench-${{ matrix.id }}-failure

.github/workflows/bench-pr.yml

Lines changed: 6 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -19,122 +19,13 @@ permissions:
1919
id-token: write # enables AWS-GitHub OIDC
2020

2121
jobs:
22+
# Rust micro-benchmarks (random access, compression). Matrix resolved from the `micro` profile.
2223
bench:
23-
timeout-minutes: 120
24-
runs-on: >-
25-
${{ github.repository == 'vortex-data/vortex'
26-
&& format('runs-on={0}/runner=bench-dedicated/tag={1}{2}', github.run_id, matrix.benchmark.id, github.event.pull_request.head.repo.fork == false && '/extras=s3-cache' || '')
27-
|| 'ubuntu-latest' }}
28-
strategy:
29-
matrix:
30-
benchmark:
31-
- id: random-access-bench
32-
name: Random Access
33-
build_args: "--features lance"
34-
- id: compress-bench
35-
name: Compression
36-
steps:
37-
- uses: runs-on/action@v2
38-
if: github.event.pull_request.head.repo.fork == false
39-
with:
40-
sccache: s3
41-
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
42-
with:
43-
ref: ${{ github.event.pull_request.head.sha }}
44-
- name: Setup benchmark environment
45-
run: sudo bash scripts/setup-benchmark.sh
46-
- uses: ./.github/actions/setup-rust
47-
with:
48-
repo-token: ${{ secrets.GITHUB_TOKEN }}
49-
enable-sccache: ${{ github.event.pull_request.head.repo.fork == false && 'true' || 'false' }}
50-
51-
- name: Install DuckDB
52-
run: |
53-
wget -qO- https://github.com/duckdb/duckdb/releases/download/v1.5.4/duckdb_cli-linux-amd64.zip | funzip > duckdb
54-
chmod +x duckdb
55-
echo "$PWD" >> $GITHUB_PATH
56-
57-
- uses: ./.github/actions/system-info
58-
59-
- name: Build binary
60-
shell: bash
61-
env:
62-
RUSTFLAGS: "-C target-cpu=native"
63-
run: |
64-
cargo build --package ${{ matrix.benchmark.id }} --profile release_debug ${{ matrix.benchmark.build_args }} --features unstable_encodings
65-
66-
- name: Setup Polar Signals
67-
if: github.event.pull_request.head.repo.fork == false
68-
uses: polarsignals/gh-actions-ps-profiling@68ae857e375a826606352016e5b90f01a2a7ff7a # v0.8.1
69-
with:
70-
polarsignals_cloud_token: ${{ secrets.POLAR_SIGNALS_API_KEY }}
71-
labels: "branch=${{ github.ref_name }};gh_run_id=${{ github.run_id }};benchmark=${{ matrix.benchmark.id }}"
72-
project_uuid: "e5d846e1-b54c-46e7-9174-8bf055a3af56"
73-
profiling_frequency: 199
74-
extra_args: "--off-cpu-threshold=0.03" # Personally tuned by @brancz
75-
76-
- name: Run ${{ matrix.benchmark.name }} benchmark (per-combination)
77-
if: matrix.benchmark.id == 'random-access-bench'
78-
shell: bash
79-
env:
80-
RUST_BACKTRACE: full
81-
VORTEX_EXPERIMENTAL_PATCHED_ARRAY: "1"
82-
FLAT_LAYOUT_INLINE_ARRAY_NODE: "1"
83-
run: |
84-
python3 scripts/random-access-split.py
85-
86-
- name: Run ${{ matrix.benchmark.name }} benchmark
87-
if: matrix.benchmark.id != 'random-access-bench'
88-
shell: bash
89-
env:
90-
RUST_BACKTRACE: full
91-
VORTEX_EXPERIMENTAL_PATCHED_ARRAY: "1"
92-
FLAT_LAYOUT_INLINE_ARRAY_NODE: "1"
93-
run: |
94-
bash scripts/bench-taskset.sh target/release_debug/${{ matrix.benchmark.id }} -d gh-json -o results.json
95-
96-
- name: Setup AWS CLI
97-
if: github.event.pull_request.head.repo.fork == false
98-
uses: aws-actions/configure-aws-credentials@e7f100cf4c008499ea8adda475de1042d6975c7b # v6
99-
with:
100-
role-to-assume: arn:aws:iam::245040174862:role/GitHubBenchmarkRole
101-
aws-region: us-east-1
102-
103-
- name: Install uv
104-
uses: spiraldb/actions/.github/actions/setup-uv@a746510eafaa926484c354541cfc49b2ec06cc63 # 0.18.6
105-
with:
106-
sync: false
107-
108-
- name: Compare results
109-
shell: bash
110-
run: |
111-
set -Eeu -o pipefail -x
112-
113-
python3 scripts/s3-download.py s3://vortex-ci-benchmark-results/data.json.gz data.json.gz --no-sign-request
114-
gzip -d -c data.json.gz > base.json
115-
116-
echo '# Benchmarks: ${{ matrix.benchmark.name }}' > comment.md
117-
echo '' >> comment.md
118-
uv run --no-project scripts/compare-benchmark-jsons.py base.json results.json "${{ matrix.benchmark.name }}" \
119-
>> comment.md
120-
cat comment.md >> $GITHUB_STEP_SUMMARY
121-
122-
- name: Comment PR
123-
if: github.event.pull_request.head.repo.fork == false
124-
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3
125-
with:
126-
file-path: comment.md
127-
comment-tag: bench-pr-comment-${{ matrix.benchmark.id }}
128-
129-
- name: Comment PR on failure
130-
if: failure() && github.event.pull_request.head.repo.fork == false
131-
uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3
132-
with:
133-
message: |
134-
# BENCHMARK FAILED
135-
136-
Benchmark `${{ matrix.benchmark.name }}` failed! Check the [workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.
137-
comment-tag: bench-pr-comment-${{ matrix.benchmark.id }}
24+
uses: ./.github/workflows/bench-core.yml
25+
secrets: inherit
26+
with:
27+
mode: "pr"
28+
profile: "micro"
13829

13930
sql:
14031
uses: ./.github/workflows/sql-benchmarks.yml

0 commit comments

Comments
 (0)