Перейти до основного вмісту
Модуль 9 · Урок 3 із 543/50 у курсі~12 min
Модульні уроки (3/5)

Еталонні показники та профілі

Окрім функціональних тестів, go test також має вбудовані тести (BenchmarkXxx) і підтримує профілі ЦП і пам’яті (pprof). Все без зовнішніх залежностей.

Форма репера

Go
func BenchmarkSum(b *testing.B) {
    for i := 0; i < b.N; i++ {
        _ = Sum(2, 3)
    }
}

Характеристики:

  • Точний підпис: func BenchmarkXxx(b *testing.B).
  • Цикл має виконуватися b.N ітерацій: фреймворк налаштовує b.N автоматично, починаючи з 1 і збільшуючи, доки вимірювання не стабілізується (~1 секунда за замовчуванням).
  • Результат ns/op (наносекунди на операцію), а з -benchmem також B/op і allocs/op.

Типові команди

Bash
go test -bench=. ./...              # all benchmarks
go test -bench=Sum -benchmem        # only Sum, with memory info
go test -bench=. -benchtime=5s      # each benchmark for 5 seconds
go test -bench=. -cpuprofile=cpu.out # generate a CPU profile

Типовий вихід:

Code
BenchmarkSum-8        1000000000        0.31 ns/op

-8 це значення GOMAXPROCS. 0.31 ns/op середній час виклику.

Дороге налаштування: b.ResetTimer

Якщо у вас довгий етап підготовки перед петлею, виключіть його з вимірювання:

Go
func BenchmarkSearch(b *testing.B) {
    data := buildLargeSlice(1_000_000) // expensive
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        _ = Search(data, 42)
    }
}

Корисні варіанти:

  • b.StopTimer() / b.StartTimer() — призупинити вимірювання навколо нецікавої фази (зручно всередині циклу).
  • b.ReportAllocs() — примусове звітування про розподіл навіть без -benchmem.

Таблиця порівняння з b.Run

Так само, як t.Run для тестів, існує b.Run для параметричних тестів:

Go
func BenchmarkSplit(b *testing.B) {
    for _, size := range []int{10, 1000, 100000} {
        b.Run(fmt.Sprintf("n=%d", size), func(b *testing.B) {
            s := strings.Repeat("a,", size)
            b.ResetTimer()
            for i := 0; i < b.N; i++ {
                _ = strings.Split(s, ",")
            }
        })
    }
}

Виведіть такі рядки, як BenchmarkSplit/n=10-8, BenchmarkSplit/n=1000-8, ... ідеально підходить для масштабування діаграм.

Порівняння двох реалізацій із benchstat

Bash
go test -bench=. -count=10 > old.txt
# apply change
go test -bench=. -count=10 > new.txt
benchstat old.txt new.txt

benchstat (у golang.org/x/perf/cmd/benchstat) обчислює середнє значення, стандартне відхилення та статистичну значущість різниці.

вправи

вправи#go.m9.l3.e1
Спроби: 0Завантаження…

Визначте BenchmarkSum за допомогою циклу над b.N, який викликає Sum(2, 3).

Завантаження редактора…

Рішення доступне після 3 спроб

вправи#go.m9.l3.e2
Спроби: 0Завантаження…

Додайте b.ResetTimer ПІСЛЯ дорогого налаштування, перед циклом, щоб налаштування не було включено до вимірювання.

Завантаження редактора…

Рішення доступне після 3 спроб

Quiz#go.m9.l3.e3
Готовий

Який прапор запускає всі тести в пакеті?

Go
$ go test ???
Варіанти відповідей