@@ -91,6 +91,10 @@ type codspeed struct {
91
91
codspeedTimePerRoundNs []time.Duration
92
92
codspeedItersPerRound []int64
93
93
startTimestamp uint64
94
+
95
+ // Accumulated timestamp pairs for batch submission
96
+ accumulatedStartTimestamps []uint64
97
+ accumulatedEndTimestamps []uint64
94
98
}
95
99
96
100
// B is a type passed to [Benchmark] functions to manage benchmark
@@ -176,14 +180,17 @@ func (b *B) StopTimer() {
176
180
// b.loop.i |= loopPoisonTimer
177
181
178
182
endTimestamp := capi .CurrentTimestamp ()
179
- b .codspeed .instrument_hooks .AddBenchmarkTimestamps (b .codspeed .startTimestamp , endTimestamp )
183
+
184
+ // Accumulate timestamps for batch submission instead of immediate hook call
185
+ b .codspeed .accumulatedStartTimestamps = append (b .codspeed .accumulatedStartTimestamps , b .codspeed .startTimestamp )
186
+ b .codspeed .accumulatedEndTimestamps = append (b .codspeed .accumulatedEndTimestamps , endTimestamp )
180
187
181
188
// For b.N loops: This will be called in runN which sets b.N to the number of iterations.
182
189
// For b.Loop() loops: loopSlowPath sets b.N to 0 to prevent b.N loops within b.Loop. However, since
183
190
// we're starting/stopping the timer for each iteration in the b.Loop() loop, we can use 1 as
184
191
// the number of iterations for this round.
185
- b .codspeedItersPerRound = append (b .codspeedItersPerRound , max (int64 (b .N ), 1 ))
186
- b .codspeedTimePerRoundNs = append (b .codspeedTimePerRoundNs , highPrecisionTimeSince (b .start ))
192
+ b .codspeed . codspeedItersPerRound = append (b . codspeed .codspeedItersPerRound , max (int64 (b .N ), 1 ))
193
+ b .codspeed . codspeedTimePerRoundNs = append (b . codspeed .codspeedTimePerRoundNs , highPrecisionTimeSince (b .start ))
187
194
}
188
195
}
189
196
@@ -207,6 +214,21 @@ func (b *B) ResetTimer() {
207
214
b .duration = 0
208
215
b .netAllocs = 0
209
216
b .netBytes = 0
217
+
218
+ // Clear accumulated CodSpeed timestamp data
219
+ b .codspeed .codspeedItersPerRound = b .codspeed .codspeedItersPerRound [:0 ]
220
+ b .codspeed .codspeedTimePerRoundNs = b .codspeed .codspeedTimePerRoundNs [:0 ]
221
+ b .codspeed .accumulatedStartTimestamps = b .codspeed .accumulatedStartTimestamps [:0 ]
222
+ b .codspeed .accumulatedEndTimestamps = b .codspeed .accumulatedEndTimestamps [:0 ]
223
+ }
224
+
225
+ func (b * B ) submitAccumulatedTimestamps () {
226
+ for i := 0 ; i < len (b .codspeed .accumulatedStartTimestamps ); i ++ {
227
+ b .codspeed .instrument_hooks .AddBenchmarkTimestamps (
228
+ b .codspeed .accumulatedStartTimestamps [i ],
229
+ b .codspeed .accumulatedEndTimestamps [i ],
230
+ )
231
+ }
210
232
}
211
233
212
234
// SetBytes records the number of bytes processed in a single operation.
@@ -391,8 +413,10 @@ func (b *B) launch() {
391
413
}
392
414
393
415
// Reset the fields from the warmup run
394
- b .codspeedItersPerRound = make ([]int64 , 0 )
395
- b .codspeedTimePerRoundNs = make ([]time.Duration , 0 )
416
+ b .codspeed .codspeedItersPerRound = make ([]int64 , 0 )
417
+ b .codspeed .codspeedTimePerRoundNs = make ([]time.Duration , 0 )
418
+ b .codspeed .accumulatedStartTimestamps = make ([]uint64 , 0 )
419
+ b .codspeed .accumulatedEndTimestamps = make ([]uint64 , 0 )
396
420
397
421
// Final run:
398
422
benchD := time .Second * b .benchTime .d
@@ -419,7 +443,11 @@ func (b *B) launch() {
419
443
b .codspeed .instrument_hooks .StopBenchmark ()
420
444
}
421
445
}
422
- b .result = BenchmarkResult {b .N , b .duration , b .bytes , b .netAllocs , b .netBytes , b .codspeedTimePerRoundNs , b .codspeedItersPerRound , b .extra }
446
+
447
+ // Submit all accumulated timestamps to CodSpeed hooks before finalizing results
448
+ b .submitAccumulatedTimestamps ()
449
+
450
+ b .result = BenchmarkResult {b .N , b .duration , b .bytes , b .netAllocs , b .netBytes , b .codspeed .codspeedTimePerRoundNs , b .codspeed .codspeedItersPerRound , b .extra }
423
451
}
424
452
425
453
// Elapsed returns the measured elapsed time of the benchmark.
@@ -458,6 +486,10 @@ func (b *B) stopOrScaleBLoop() bool {
458
486
// Stop the timer so we don't count cleanup time
459
487
b .StopTimer ()
460
488
b .codspeed .instrument_hooks .StopBenchmark ()
489
+
490
+ // Submit all accumulated timestamps to CodSpeed hooks before benchmark completion
491
+ b .submitAccumulatedTimestamps ()
492
+
461
493
// Commit iteration count
462
494
b .N = int (b .loop .n )
463
495
b .loop .done = true
@@ -496,8 +528,10 @@ func (b *B) loopSlowPath() bool {
496
528
b .N = 0
497
529
b .loop .i ++
498
530
499
- b .codspeedItersPerRound = make ([]int64 , 0 )
500
- b .codspeedTimePerRoundNs = make ([]time.Duration , 0 )
531
+ b .codspeed .codspeedItersPerRound = make ([]int64 , 0 )
532
+ b .codspeed .codspeedTimePerRoundNs = make ([]time.Duration , 0 )
533
+ b .codspeed .accumulatedStartTimestamps = make ([]uint64 , 0 )
534
+ b .codspeed .accumulatedEndTimestamps = make ([]uint64 , 0 )
501
535
502
536
b .codspeed .instrument_hooks .StartBenchmark ()
503
537
b .ResetTimer ()
@@ -515,6 +549,10 @@ func (b *B) loopSlowPath() bool {
515
549
}
516
550
b .StopTimer ()
517
551
b .codspeed .instrument_hooks .StopBenchmark ()
552
+
553
+ // Submit all accumulated timestamps to CodSpeed hooks before benchmark completion
554
+ b .submitAccumulatedTimestamps ()
555
+
518
556
// Commit iteration count
519
557
b .N = int (b .loop .n )
520
558
b .loop .done = true
@@ -900,8 +938,8 @@ func (s *benchState) processBench(b *B) {
900
938
Name : benchName ,
901
939
Uri : benchUri ,
902
940
Pid : os .Getpid (),
903
- CodspeedTimePerRoundNs : r .CodspeedTimePerRoundNs ,
904
- CodspeedItersPerRound : r .CodspeedItersPerRound ,
941
+ CodspeedTimePerRoundNs : r .codspeedTimePerRoundNs ,
942
+ CodspeedItersPerRound : r .codspeedItersPerRound ,
905
943
}
906
944
907
945
goRunnerMetadata , err := findGoRunnerMetadata ()
0 commit comments