|
| 1 | +diff --git a/testing/testing/benchmark.go b/testing/testing/benchmark.go |
| 2 | +index 8fdea90..9473443 100644 |
| 3 | +--- a/testing/testing/benchmark.go |
| 4 | ++++ b/testing/testing/benchmark.go |
| 5 | +@@ -93,6 +93,10 @@ type codspeed struct { |
| 6 | + startTimestamp uint64 |
| 7 | + startTimestamps []uint64 |
| 8 | + stopTimestamps []uint64 |
| 9 | ++ |
| 10 | ++ // Indicates whether a measurement has been saved already. This aims to prevent saving measurements |
| 11 | ++ // twice, because `b.Loop()` saves them internally as well but is also called from runN |
| 12 | ++ savedMeasurement bool |
| 13 | + } |
| 14 | + |
| 15 | + // B is a type passed to [Benchmark] functions to manage benchmark |
| 16 | +@@ -160,6 +164,7 @@ func (b *B) StartTimerWithoutMarker() { |
| 17 | + // b.startBytes = memStats.TotalAlloc |
| 18 | + b.start = highPrecisionTimeNow() |
| 19 | + b.timerOn = true |
| 20 | ++ b.savedMeasurement = false |
| 21 | + // b.loop.i &^= loopPoisonTimer |
| 22 | + } |
| 23 | + } |
| 24 | +@@ -186,14 +191,22 @@ func (b *B) StopTimerWithoutMarker() { |
| 25 | + b.timerOn = false |
| 26 | + // If we hit B.Loop with the timer stopped, fail. |
| 27 | + // b.loop.i |= loopPoisonTimer |
| 28 | ++ } |
| 29 | ++} |
| 30 | + |
| 31 | +- // For b.N loops: This will be called in runN which sets b.N to the number of iterations. |
| 32 | +- // For b.Loop() loops: loopSlowPath sets b.N to 0 to prevent b.N loops within b.Loop. However, since |
| 33 | +- // we're starting/stopping the timer for each iteration in the b.Loop() loop, we can use 1 as |
| 34 | +- // the number of iterations for this round. |
| 35 | +- b.codspeedItersPerRound = append(b.codspeedItersPerRound, max(int64(b.N), 1)) |
| 36 | +- b.codspeedTimePerRoundNs = append(b.codspeedTimePerRoundNs, timeSinceStart) |
| 37 | ++func (b *B) SaveMeasurement() { |
| 38 | ++ if b.savedMeasurement { |
| 39 | ++ return |
| 40 | + } |
| 41 | ++ b.savedMeasurement = true |
| 42 | ++ |
| 43 | ++ // For b.N loops: This will be called in runN which sets b.N to the number of iterations. |
| 44 | ++ // For b.Loop() loops: loopSlowPath sets b.N to 0 to prevent b.N loops within b.Loop. However, since |
| 45 | ++ // we're starting/stopping the timer for each iteration in the b.Loop() loop, we can use 1 as |
| 46 | ++ // the number of iterations for this round. |
| 47 | ++ timeSinceStart := highPrecisionTimeSince(b.start) |
| 48 | ++ b.codspeedItersPerRound = append(b.codspeedItersPerRound, max(int64(b.N), 1)) |
| 49 | ++ b.codspeedTimePerRoundNs = append(b.codspeedTimePerRoundNs, timeSinceStart) |
| 50 | + } |
| 51 | + |
| 52 | + func (b *B) StopTimer() { |
| 53 | +@@ -296,6 +309,7 @@ func (b *B) __codspeed_root_frame__runN(n int) { |
| 54 | + b.ResetTimer() |
| 55 | + b.StartTimer() |
| 56 | + b.benchFunc(b) |
| 57 | ++ b.SaveMeasurement() |
| 58 | + b.StopTimer() |
| 59 | + b.previousN = n |
| 60 | + b.previousDuration = b.duration |
| 61 | +@@ -614,6 +628,7 @@ func (b *B) loopSlowPath() bool { |
| 62 | + // whereas b.N-based benchmarks must run the benchmark function (and any |
| 63 | + // associated setup and cleanup) several times. |
| 64 | + func (b *B) Loop() bool { |
| 65 | ++ b.SaveMeasurement() |
| 66 | + b.StopTimerWithoutMarker() |
| 67 | + // This is written such that the fast path is as fast as possible and can be |
| 68 | + // inlined. |
0 commit comments