Skip to content

Commit 205040b

Browse files
committed
test
1 parent e33382b commit 205040b

File tree

3 files changed

+467
-0
lines changed

3 files changed

+467
-0
lines changed
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
name: Build Benchmark
2+
3+
on:
4+
schedule:
5+
# Run nightly at 2 AM UTC (matching nightly.yml)
6+
- cron: '0 2 * * *'
7+
workflow_dispatch:
8+
inputs:
9+
branch:
10+
description: 'Branch to benchmark (leave empty for current branch)'
11+
required: false
12+
default: ''
13+
base_branch:
14+
description: 'Base branch for comparison'
15+
required: false
16+
default: 'develop'
17+
warmups:
18+
description: 'Number of warmup iterations'
19+
required: false
20+
default: '4'
21+
iterations:
22+
description: 'Number of measured iterations'
23+
required: false
24+
default: '7'
25+
26+
jobs:
27+
benchmark:
28+
name: Run Benchmark
29+
runs-on: ubuntu-24.04
30+
timeout-minutes: 120
31+
strategy:
32+
matrix:
33+
target: [head, base]
34+
35+
steps:
36+
- name: Determine branch to benchmark
37+
id: determine-branch
38+
run: |
39+
if [ "${{ matrix.target }}" == "head" ]; then
40+
if [ "${{ github.event_name }}" == "schedule" ]; then
41+
BRANCH="develop"
42+
else
43+
# workflow_dispatch
44+
BRANCH="${{ github.event.inputs.branch }}"
45+
if [ -z "$BRANCH" ]; then
46+
BRANCH="${{ github.ref_name }}"
47+
fi
48+
fi
49+
else
50+
# base target
51+
if [ "${{ github.event_name }}" == "schedule" ]; then
52+
# For nightly, skip base (we'll compare with previous run)
53+
echo "skip=true" >> $GITHUB_OUTPUT
54+
exit 0
55+
else
56+
# workflow_dispatch
57+
BRANCH="${{ github.event.inputs.base_branch }}"
58+
fi
59+
fi
60+
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
61+
echo "skip=false" >> $GITHUB_OUTPUT
62+
echo "Benchmarking ${{ matrix.target }} branch: $BRANCH"
63+
64+
- name: Checkout repository
65+
if: steps.determine-branch.outputs.skip != 'true'
66+
uses: actions/checkout@v4
67+
with:
68+
ref: ${{ steps.determine-branch.outputs.branch }}
69+
submodules: recursive
70+
71+
- name: Set up Java
72+
if: steps.determine-branch.outputs.skip != 'true'
73+
uses: actions/setup-java@v4
74+
with:
75+
distribution: 'temurin'
76+
java-version: '17'
77+
78+
- name: Setup Gradle
79+
if: steps.determine-branch.outputs.skip != 'true'
80+
uses: gradle/actions/setup-gradle@v4
81+
with:
82+
cache-read-only: true
83+
84+
- name: Install SDKMAN
85+
if: steps.determine-branch.outputs.skip != 'true'
86+
run: |
87+
curl -s "https://get.sdkman.io" | bash
88+
source "$HOME/.sdkman/bin/sdkman-init.sh"
89+
sdk version
90+
91+
- name: Install Gradle Profiler
92+
if: steps.determine-branch.outputs.skip != 'true'
93+
run: |
94+
source "$HOME/.sdkman/bin/sdkman-init.sh"
95+
sdk install gradleprofiler
96+
gradle-profiler --version
97+
98+
- name: Warm up build cache
99+
if: steps.determine-branch.outputs.skip != 'true'
100+
run: |
101+
./gradlew assembleInternalDebug --no-daemon
102+
103+
- name: Create dynamic scenarios file
104+
if: |
105+
steps.determine-branch.outputs.skip != 'true' &&
106+
github.event_name == 'workflow_dispatch' &&
107+
(github.event.inputs.warmups != '4' || github.event.inputs.iterations != '7')
108+
run: |
109+
WARMUPS="${{ github.event.inputs.warmups }}"
110+
ITERATIONS="${{ github.event.inputs.iterations }}"
111+
112+
sed -i "s/warm-ups = 4/warm-ups = $WARMUPS/g" build_performance.scenarios
113+
sed -i "s/iterations = 7/iterations = $ITERATIONS/g" build_performance.scenarios
114+
115+
echo "Updated scenarios file with warmups=$WARMUPS, iterations=$ITERATIONS"
116+
117+
- name: Run Build Benchmarks
118+
if: steps.determine-branch.outputs.skip != 'true'
119+
run: |
120+
source "$HOME/.sdkman/bin/sdkman-init.sh"
121+
gradle-profiler --benchmark --scenario-file build_performance.scenarios --output-dir profile-out-${{ matrix.target }}
122+
123+
- name: Upload Benchmark Results
124+
if: steps.determine-branch.outputs.skip != 'true'
125+
uses: actions/upload-artifact@v4
126+
with:
127+
name: benchmark-results-${{ matrix.target }}-${{ github.run_number }}
128+
path: profile-out-${{ matrix.target }}/**/*.csv
129+
retention-days: 30
130+
131+
compare-results:
132+
name: Compare Results
133+
runs-on: ubuntu-24.04
134+
needs: benchmark
135+
if: always() && needs.benchmark.result == 'success'
136+
137+
steps:
138+
- name: Checkout repository
139+
uses: actions/checkout@v4
140+
141+
- name: Download Head Results
142+
uses: actions/download-artifact@v4
143+
with:
144+
name: benchmark-results-head-${{ github.run_number }}
145+
path: profile-out-head
146+
147+
- name: Download Base Results (if not nightly)
148+
if: github.event_name != 'schedule'
149+
uses: actions/download-artifact@v4
150+
with:
151+
name: benchmark-results-base-${{ github.run_number }}
152+
path: profile-out-base
153+
154+
- name: Compute Previous Run Number
155+
if: github.event_name == 'schedule'
156+
id: prev-run
157+
run: echo "previous=$(( ${{ github.run_number }} - 1 ))" >> $GITHUB_OUTPUT
158+
159+
- name: Download Previous Nightly Results
160+
if: github.event_name == 'schedule'
161+
uses: actions/download-artifact@v4
162+
continue-on-error: true
163+
with:
164+
name: benchmark-results-head-${{ steps.prev-run.outputs.previous }}
165+
path: profile-out-base
166+
167+
- name: Compare Results
168+
run: |
169+
if [ -f "profile-out-base/benchmark.csv" ]; then
170+
python3 scripts/benchmark-comparison.py \
171+
profile-out-head/benchmark.csv \
172+
profile-out-base/benchmark.csv
173+
else
174+
python3 scripts/benchmark-comparison.py profile-out-head/benchmark.csv
175+
fi
176+
177+
- name: Upload Comparison Report
178+
uses: actions/upload-artifact@v4
179+
with:
180+
name: benchmark-comparison-${{ github.run_number }}
181+
path: benchmark-result.md
182+
retention-days: 30

build_performance.scenarios

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Gradle Profiler Build Performance Scenarios
2+
# This file defines three benchmark scenarios to measure build performance
3+
4+
# Scenario 1: Clean Build
5+
# Measures cold build performance with no incremental compilation
6+
clean-build {
7+
title = "Clean Build"
8+
versions = ["8.14"]
9+
tasks = ["assembleInternalDebug"]
10+
gradle-args = ["--no-build-cache", "--no-configuration-cache"]
11+
cleanup-tasks = ["clean"]
12+
warm-ups = 4
13+
iterations = 7
14+
15+
# Use daemon for consistency
16+
daemon = warm
17+
}
18+
19+
# Scenario 2: ABI Change
20+
# Measures incremental build performance when public API changes
21+
# This triggers recompilation of all dependent modules
22+
abi-change {
23+
title = "ABI Change (Incremental)"
24+
versions = ["8.14"]
25+
tasks = ["assembleInternalDebug"]
26+
gradle-args = ["--no-build-cache", "--no-configuration-cache"]
27+
28+
# Apply ABI change to a core utility class
29+
# Gradle profiler will modify a public method signature
30+
apply-abi-change-to = "app/src/main/java/com/duckduckgo/app/global/DispatcherProvider.kt"
31+
32+
warm-ups = 4
33+
iterations = 7
34+
daemon = warm
35+
}
36+
37+
# Scenario 3: Non-ABI Change
38+
# Measures incremental build performance when only implementation changes
39+
# Only the modified module needs recompilation
40+
non-abi-change {
41+
title = "Non-ABI Change (Incremental)"
42+
versions = ["8.14"]
43+
tasks = ["assembleInternalDebug"]
44+
gradle-args = ["--no-build-cache", "--no-configuration-cache"]
45+
46+
# Apply non-ABI change to the same file
47+
# Gradle profiler will modify method implementation without changing signature
48+
apply-non-abi-change-to = "app/src/main/java/com/duckduckgo/app/global/DispatcherProvider.kt"
49+
50+
warm-ups = 4
51+
iterations = 7
52+
daemon = warm
53+
}

0 commit comments

Comments
 (0)