Skip to content

Commit 3ba284c

Browse files
committed
fix(testing): emit markers for benchmarks using b.Loop()
1 parent a6c2549 commit 3ba284c

4 files changed

Lines changed: 67 additions & 10 deletions

File tree

testing/fork.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ restore_files "${CODSPEED_FILES[@]}"
123123

124124
apply_patch "patches/benchmark_stopbenchmark_fail.patch" 10 ".."
125125
apply_patch "patches/benchmark_stoptimer_mitigation.patch" 10 ".."
126+
apply_patch "patches/benchmark_benchmarkers_bloop.patch" 10 ".."
126127

127128

128129
# Run pre-commit and format the code
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
diff --git a/testing/testing/benchmark.go b/testing/testing/benchmark.go
2+
index 4947e11..0040973 100644
3+
--- a/testing/testing/benchmark.go
4+
+++ b/testing/testing/benchmark.go
5+
@@ -226,15 +226,7 @@ func (b *B) StopTimer() {
6+
b.StopTimerWithoutMarker()
7+
8+
if timerOn {
9+
- if b.startTimestamp >= endTimestamp {
10+
- // This should never happen, unless we have a bug in the timer logic.
11+
- panic(fmt.Sprintf("Invalid benchmark timestamps: start timestamp (%d) is greater than or equal to end timestamp (%d)", b.startTimestamp, endTimestamp))
12+
- }
13+
- b.startTimestamps = append(b.startTimestamps, b.startTimestamp)
14+
- b.stopTimestamps = append(b.stopTimestamps, endTimestamp)
15+
-
16+
- // Reset to prevent accidental reuse
17+
- b.startTimestamp = 0
18+
+ b.AddBenchmarkMarkers(endTimestamp)
19+
}
20+
}
21+
22+
@@ -587,7 +579,18 @@ func (b *B) loopSlowPath() bool {
23+
more = b.stopOrScaleBLoop()
24+
}
25+
if !more {
26+
- b.StopTimerWithoutMarker()
27+
+ // NOTE: We could move the endTimestamp capturing further up or even into the Loop() function
28+
+ // but this will result in a huge performance degradation since the C FFI calls are expensive.
29+
+ //
30+
+ // The only downside of having this here, is that there's a small chance of perf sampling the
31+
+ // benchmark framework code which already happens anyway because we only emit 1 pair of
32+
+ // start/stop markers per benchmark to minimize overhead and allow full flamegraphs.
33+
+ endTimestamp := capi.CurrentTimestamp()
34+
+
35+
+ // Edge case: The timer is stopped in b.Loop() which prevents any further calls to
36+
+ // StopTimer() from adding the benchmark markers. We have to manually submit them here,
37+
+ // once the benchmark loop is done.
38+
+ b.AddBenchmarkMarkers(endTimestamp)
39+
b.codspeed.instrument_hooks.StopBenchmark()
40+
b.sendAccumulatedTimestamps()

testing/testing/benchmark.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,7 @@ func (b *B) StopTimer() {
226226
b.StopTimerWithoutMarker()
227227

228228
if timerOn {
229-
if b.startTimestamp >= endTimestamp {
230-
// This should never happen, unless we have a bug in the timer logic.
231-
panic(fmt.Sprintf("Invalid benchmark timestamps: start timestamp (%d) is greater than or equal to end timestamp (%d)", b.startTimestamp, endTimestamp))
232-
}
233-
b.startTimestamps = append(b.startTimestamps, b.startTimestamp)
234-
b.stopTimestamps = append(b.stopTimestamps, endTimestamp)
235-
236-
// Reset to prevent accidental reuse
237-
b.startTimestamp = 0
229+
b.AddBenchmarkMarkers(endTimestamp)
238230
}
239231
}
240232

@@ -587,7 +579,18 @@ func (b *B) loopSlowPath() bool {
587579
more = b.stopOrScaleBLoop()
588580
}
589581
if !more {
590-
b.StopTimerWithoutMarker()
582+
// NOTE: We could move the endTimestamp capturing further up or even into the Loop() function
583+
// but this will result in a huge performance degradation since the C FFI calls are expensive.
584+
//
585+
// The only downside of having this here, is that there's a small chance of perf sampling the
586+
// benchmark framework code which already happens anyway because we only emit 1 pair of
587+
// start/stop markers per benchmark to minimize overhead and allow full flamegraphs.
588+
endTimestamp := capi.CurrentTimestamp()
589+
590+
// Edge case: The timer is stopped in b.Loop() which prevents any further calls to
591+
// StopTimer() from adding the benchmark markers. We have to manually submit them here,
592+
// once the benchmark loop is done.
593+
b.AddBenchmarkMarkers(endTimestamp)
591594
b.codspeed.instrument_hooks.StopBenchmark()
592595
b.sendAccumulatedTimestamps()
593596

testing/testing/codspeed.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,16 @@ func getGitRelativePath(absPath string) string {
7474
func ensureBenchmarkIsStopped(b *B) {
7575
b.codspeed.instrument_hooks.StopBenchmark()
7676
}
77+
78+
func (b *B) AddBenchmarkMarkers(endTimestamp uint64) {
79+
if b.startTimestamp >= endTimestamp {
80+
// This should never happen, unless we have a bug in the timer logic.
81+
panic(fmt.Sprintf("Invalid benchmark timestamps: start timestamp (%d) is greater than or equal to end timestamp (%d)", b.startTimestamp, endTimestamp))
82+
}
83+
84+
b.startTimestamps = append(b.startTimestamps, b.startTimestamp)
85+
b.stopTimestamps = append(b.stopTimestamps, endTimestamp)
86+
87+
// Reset to prevent accidental reuse
88+
b.startTimestamp = 0
89+
}

0 commit comments

Comments
 (0)