Метод testing.B.Run

Метод testing.B.Run запускает вложенный бенчмарк или подтест внутри родительского бенчмарка. Первым параметром метод принимает строку с именем подбенчмарка, вторым - функцию типа func(b *testing.B), в которой выполняется измеряемый код. Метод возвращает bool, указывающее на успешность выполнения вложенного бенчмарка.

Синтаксис

gofunc (b *testing.B) Run(name string, f func(b *testing.B)) bool

Пример

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

gopackage main

import (
  "fmt"
  "testing"
)

func BenchmarkAlgorithms(b *testing.B) {
  b.Run("linear", func(b *testing.B) {
    for i := 0; i < b.N; i++ {
      linearSearch(1000)
    }
  })

  b.Run("binary", func(b *testing.B) {
    for i := 0; i < b.N; i++ {
      binarySearch(1000)
    }
  })
}

func linearSearch(n int) int {
  result := 0
  for i := 0; i < n; i++ {
    result += i
  }
  return result
}

func binarySearch(n int) int {
  if n <= 0 {
    return 0
  }
  return n + binarySearch(n-1)
}

func main() {
  fmt.Println("Run benchmarks with: go test -bench=.")
}

Пример

Метод testing.B.Run также позволяет создавать параметризованные бенчмарки с различными входными данными:

gopackage main

import (
  "fmt"
  "testing"
)

func BenchmarkStringConcat(b *testing.B) {
  sizes := []int{10, 100, 1000}

  for _, size := range sizes {
    b.Run(fmt.Sprintf("size-%d", size), func(b *testing.B) {
      data := make([]string, size)
      for i := range data {
        data[i] = "a"
      }

      b.ResetTimer()
      for i := 0; i < b.N; i++ {
        result := ""
        for _, s := range data {
          result += s
        }
        _ = result
      }
    })
  }
}

func main() {
  fmt.Println("Run benchmarks with: go test -bench=.")
}

Пример

Вложенные бенчмарки позволяют изолировать измерение производительности различных операций внутри одного бенчмарка:

gopackage main

import (
  "fmt"
  "testing"
)

func BenchmarkSliceOperations(b *testing.B) {
  b.Run("append", func(b *testing.B) {
    for i := 0; i < b.N; i++ {
      slice := make([]int, 0, 100)
      for j := 0; j < 100; j++ {
        slice = append(slice, j)
      }
    }
  })

  b.Run("preallocate", func(b *testing.B) {
    for i := 0; i < b.N; i++ {
      slice := make([]int, 100)
      for j := 0; j < 100; j++ {
        slice[j] = j
      }
    }
  })
}

func main() {
  fmt.Println("Run benchmarks with: go test -bench=.")
}

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

  • метод testing.B.N,
    который определяет количество итераций бенчмарка
  • метод testing.B.ResetTimer,
    который сбрасывает таймер бенчмарка
  • метод testing.B.StartTimer,
    который запускает таймер бенчмарка
  • метод testing.B.StopTimer,
    который останавливает таймер бенчмарка