Тип testing.B

Тип testing.B используется для написания бенчмарков в пакете testing. Он передается в функции бенчмарков вторым параметром и предоставляет методы для управления замерами производительности. Основное поле N определяет количество итераций, которое будет выполнено для получения стабильных результатов.

Бенчмарки в Go имеют особый синтаксис: они всегда начинаются со слова Benchmark и принимают указатель на testing.B. Запускаются они командой go test -bench.

Синтаксис

gofunc BenchmarkXxx(b *testing.B) {
  for i := 0; i < b.N; i++ {
    // Код для измерения
  }
}

Пример базового бенчмарка

Напишем бенчмарк для функции, которая конкатенирует строки через оператор +:

gopackage main

import (
  "testing"
)

func concat(a, b string) string {
  return a + b
}

func BenchmarkConcat(b *testing.B) {
  for i := 0; i < b.N; i++ {
    concat("hello", "world")
  }
}

Результат выполнения команды:

go"BenchmarkConcat-8  1000000000  0.2456 ns/op"

Пример с сбросом таймера

Если в бенчмарке требуется выполнить подготовительные действия, которые не должны влиять на измерения, используется метод ResetTimer:

gopackage main

import (
  "testing"
)

func BenchmarkWithSetup(b *testing.B) {
  data := make([]int, 1000)
  for i := 0; i < len(data); i++ {
    data[i] = i
  }
  
  b.ResetTimer()
  
  for i := 0; i < b.N; i++ {
    sum := 0
    for _, v := range data {
      sum += v
    }
  }
}

Пример с остановкой таймера

Метод StopTimer позволяет приостановить замер времени на время выполнения ресурсоемких операций, которые не должны учитываться в результате:

gopackage main

import (
  "testing"
)

func BenchmarkStopTimer(b *testing.B) {
  for i := 0; i < b.N; i++ {
    b.StopTimer()
    // Имитация тяжелой подготовки
    _ = make([]byte, 1024)
    b.StartTimer()
    
    // Измеряемый код
    _ = i * i
  }
}

Пример с отчетом об аллокациях

Метод ReportAllocs включает отчет о выделениях памяти в результатах бенчмарка:

gopackage main

import (
  "testing"
)

func BenchmarkAllocs(b *testing.B) {
  b.ReportAllocs()
  
  for i := 0; i < b.N; i++ {
    s := make([]int, 10)
    for j := 0; j < len(s); j++ {
      s[j] = j
    }
  }
}

Результат выполнения команды:

go"BenchmarkAllocs-8  10000000  125 ns/op  80 B/op  1 allocs/op"

Смотрите также

  • тип testing.T,
    который используется для написания обычных тестов
  • метод testing.B.ResetTimer,
    который сбрасывает таймер бенчмарка
  • метод testing.B.ReportAllocs,
    который включает отчет об аллокациях
  • метод testing.B.Run,
    который запускает вложенные бенчмарки