Skip to content

Commit 85fd256

Browse files
committed
Add benchmark job in CI
1 parent 157f03c commit 85fd256

File tree

3 files changed

+86
-7
lines changed

3 files changed

+86
-7
lines changed

.github/workflows/pull_request.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,61 @@ jobs:
1919
license_header_check_project_name: "Swift.org"
2020
unacceptable_language_check_enabled: false
2121
format_check_enabled: false
22+
bench:
23+
name: Benchmark
24+
runs-on: ubuntu-latest
25+
env:
26+
BUILD_CMD: swift build -c release
27+
BENCH_CMD: .build/release/RegexBenchmark
28+
BASELINE_FILE: benchmark-baseline
29+
COMPARE_FILE: benchmark-pr
30+
COMPARE_OUT_FILE: benchmark-results.txt
31+
steps:
32+
- name: Check out baseline branch
33+
uses: actions/checkout@v4
34+
with:
35+
ref: ${{ github.event.pull_request.base.sha }}
36+
path: base
37+
fetch-depth: 0
38+
- name: Build baseline branch
39+
working-directory: base
40+
run: |
41+
set -euo pipefail
42+
eval "$BUILD_CMD"
43+
- name: Run baseline benchmark
44+
working-directory: base
45+
run: |
46+
set -euo pipefail
47+
eval "$BENCH_CMD --save $RUNNER_TEMP/$BASELINE_FILE"
48+
test -s "$RUNNER_TEMP/$BASELINE_FILE" || { echo "Baseline not created at $BASELINE_FILE"; exit 1; }
49+
- name: Check out PR branch
50+
uses: actions/checkout@v4
51+
with:
52+
ref: ${{ github.event.pull_request.head.sha }}
53+
path: pr
54+
fetch-depth: 0
55+
- name: Build PR branch
56+
working-directory: pr
57+
run: |
58+
set -euo pipefail
59+
eval "$BUILD_CMD"
60+
- name: Run PR benchmark
61+
working-directory: pr
62+
run: |
63+
set -euo pipefail
64+
eval "$BENCH_CMD --save $RUNNER_TEMP/$COMPARE_FILE"
65+
test -s "$RUNNER_TEMP/$COMPARE_FILE" || { echo "Comparison not created at $COMPARE_FILE"; exit 1; }
66+
eval "$BENCH_CMD --compare $RUNNER_TEMP/$BASELINE_FILE" | tee "$RUNNER_TEMP/$COMPARE_OUT_FILE"
67+
- name: 📊 Compare benchmarks
68+
working-directory: pr
69+
run: |
70+
set -euo pipefail
71+
eval "$BENCH_CMD --load $RUNNER_TEMP/$COMPARE_FILE --compare $RUNNER_TEMP/$BASELINE_FILE --compare-compile-time $RUNNER_TEMP/$BASELINE_FILE" | tee "$RUNNER_TEMP/$COMPARE_OUT_FILE"
72+
- name: Upload benchmark artifacts
73+
uses: actions/upload-artifact@v4
74+
with:
75+
name: benchmark-results
76+
path: |
77+
${{ runner.temp }}/${{ env.BASELINE_FILE }}
78+
${{ runner.temp }}/${{ env.COMPARE_FILE }}
79+
${{ runner.temp }}/${{ env.COMPARE_OUT_FILE }}

Sources/RegexBenchmark/BenchmarkResults.swift

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,20 +115,20 @@ extension BenchmarkRunner {
115115
.sorted(by: {(a,b) in a.diff!.seconds < b.diff!.seconds})
116116

117117
print("Comparing against \(against)")
118-
print("=== Regressions ======================================================================")
118+
print("=== Regressions ===============================================================")
119119
for item in regressions {
120120
print(item)
121121
}
122122

123-
print("=== Improvements =====================================================================")
123+
print("=== Improvements ==============================================================")
124124
for item in improvements {
125125
print(item)
126126
}
127127

128128
#if os(macOS) && canImport(Charts)
129129
if showChart {
130130
print("""
131-
=== Comparison chart =================================================================
131+
=== Comparison chart ==========================================================
132132
Press Control-C to close...
133133
""")
134134
BenchmarkResultApp.comparisons = comparisons
@@ -234,9 +234,17 @@ extension BenchmarkResult {
234234
return "- \(name) N/A"
235235
}
236236
let percentage = (1000 * diff.seconds / baselineTime.seconds).rounded()/10
237-
let len = max(40 - name.count, 1)
238-
let nameSpacing = String(repeating: " ", count: len)
239-
return "- \(name)\(nameSpacing)\(latestTime)\t\(baselineTime)\t\(diff)\t\t\(percentage)%"
237+
let start = if name.count > 40 {
238+
"- \(name)\n" + String(repeating: " ", count: 43)
239+
} else {
240+
"- \(name, paddingTo: 40) "
241+
}
242+
return start + """
243+
\(latestTime, paddingTo: 8, alignRight: true) \
244+
\(baselineTime, paddingTo: 8, alignRight: true) \
245+
\(diff, paddingTo: 8, alignRight: true) \
246+
\(percentage, paddingTo: 5, alignRight: true)%
247+
"""
240248
}
241249

242250
var asCsv: String {
@@ -334,3 +342,16 @@ extension SuiteResult: Codable {
334342
return try decoder.decode(SuiteResult.self, from: data)
335343
}
336344
}
345+
346+
extension DefaultStringInterpolation {
347+
mutating func appendInterpolation<T>(_ value: T, paddingTo length: Int, alignRight: Bool = false) {
348+
let s = String(describing: value)
349+
let paddingCount = max(0, length - s.count)
350+
let padding = String(repeating: " ", count: paddingCount)
351+
if alignRight {
352+
appendLiteral(padding + s)
353+
} else {
354+
appendLiteral(s + padding)
355+
}
356+
}
357+
}

Sources/RegexBenchmark/Utils/Stats.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ enum Stats {}
1515

1616
extension Stats {
1717
// Maximum allowed standard deviation is 7.5% of the median runtime
18-
static let maxAllowedStdev = 0.075
18+
static let maxAllowedStdev = 0.15
1919

2020
static func tTest(_ a: Measurement, _ b: Measurement) -> Bool {
2121
// Student's t-test

0 commit comments

Comments
 (0)