B.Loop
Вы наверняка знакомы с циклом в бенчмарках (for range b.N
):
var sink int
func BenchmarkSlicesMax(b *testing.B) {
// Setup the benchmark.
s := randomSlice(10_000)
b.ResetTimer()
// Run the benchmark.
for range b.N {
sink = slices.Max(s)
}
}
Go сам управляет бенчмарком, определяет разумное значение b.N
, и пишет результаты. Это удобно.
Но есть и нюансы:
- Функция бенчмарка выполняется несколько раз, поэтому сетап тоже выполняется несколько раз (и ничего с этим не поделаешь).
- Чтобы сетап не повлиял на результат, приходится вызывать
b.ResetTimer()
. - Чтобы компилятор не заоптимизировал тестируемый код, приходится использовать
sink
.
Go 1.24 предлагает кое-что получше — testing.B.Loop
:
func BenchmarkSlicesMax(b *testing.B) {
// Setup the benchmark.
s := randomSlice(10_000)
// Run the benchmark.
for b.Loop() {
slices.Max(s)
}
}
b.Loop
решает все проблемы b.N
:
- Функция бенчмарка выполняется один раз, поэтому и сетап тоже выполняется только однажды.
- Все, что находится вне
b.Loop
, не влияет на результат, поэтомуb.ResetTimer()
не нужен. - Компилятор никогда не оптимизирует вызовы функций внутри
b.Loop
.
В общем, с выходом Go 1.24 больше нет причин использовать for range b.N
. Переходим на b.Loop
!
★ Подписывайтесь на новые заметки.