ข้ามไปยังเนื้อหา

Benchmarks

ใน JavaScript คุณใช้ console.time / console.timeEnd เวลาอยากวัดแบบเร็ว ๆ หรือใช้ benchmark.js สำหรับ micro-benchmark ที่รัดกุมทางสถิติ ทั้งสองตัวรันอยู่นอก test runner และต้องตั้งค่าแยกต่างหาก

ใน Go benchmark อยู่ในไฟล์ _test.go เดียวกับ unit test คุณรันด้วยคำสั่ง go test เดิม — แค่เพิ่ม flag เข้าไป toolchain จัดการ statistical warmup ให้อัตโนมัติ

หมายเหตุเรื่อง Playground: benchmark ต้องรันใน binary context ของ go test -bench บล็อกโค้ดด้านล่างคือไฟล์ benchmark จริง — รันบนเครื่องคุณ

TypeScript
// JavaScript — benchmark.js (ไลบรารีภายนอก)
import Benchmark from 'benchmark';
const suite = new Benchmark.Suite();
suite
.add('sum-loop', () => {
let total = 0;
for (let i = 0; i < 1000; i++) total += i;
})
.on('complete', function () {
console.log(this[0].toString());
})
.run();
Go
// Go — built-in ใน testing package
// sum_test.go
package main
import "testing"
func sum(n int) int {
total := 0
for i := 0; i < n; i++ {
total += i
}
return total
}
func BenchmarkSum(b *testing.B) {
for b.Loop() { // Go 1.24+: b.Loop() เป็น form ที่แนะนำ
sum(1000)
}
}
Terminal window
# รัน benchmarks ทั้งหมดใน package ปัจจุบัน
go test -bench=. ./...
# รัน benchmarks ที่ match regex
go test -bench=BenchmarkSum ./...
# รัน unit tests ควบคู่ไปกับ benchmarks ด้วย
go test -bench=. -run=. ./...
# ข้าม unit tests (รันเฉพาะ benchmarks)
go test -bench=. -run='^$' ./...
# ควบคุมเวลา benchmark (default 1s)
go test -bench=. -benchtime=5s ./...
# รายงาน memory allocations
go test -bench=. -benchmem ./...
BenchmarkSum-8 14253187 84.23 ns/op
BenchmarkSum-8 14253187 84.23 ns/op 0 B/op 0 allocs/op
คอลัมน์ความหมาย
BenchmarkSum-8ชื่อ Benchmark + GOMAXPROCS (จำนวน CPU)
14253187จำนวน iterations (b.N) ที่ runner เลือก
84.23 ns/opNanoseconds ต่อ operation
0 B/opBytes ที่ allocate ต่อ operation (-benchmem)
0 allocs/opHeap allocations ต่อ operation (-benchmem)

Go runner จะค่อย ๆ เพิ่ม b.N จนผลลัพธ์นิ่งทางสถิติ — คุณไม่ต้อง hardcode จำนวน iteration เอง

strings_test.go
package strings_test
import (
"strings"
"testing"
)
func BenchmarkConcatPlus(b *testing.B) {
for b.Loop() {
var s string
for i := 0; i < 100; i++ {
s += "x" // allocates ทุก iteration
}
_ = s
}
}
func BenchmarkConcatBuilder(b *testing.B) {
for b.Loop() {
var sb strings.Builder
for i := 0; i < 100; i++ {
sb.WriteByte('x') // single pre-allocated buffer
}
_ = sb.String()
}
}

รันด้วย -benchmem เพื่อดูว่า allocation ต่างกันมากแค่ไหน:

BenchmarkConcatPlus-8 228468 5213 ns/op 5440 B/op 99 allocs/op
BenchmarkConcatBuilder-8 2134500 562 ns/op 128 B/op 1 allocs/op
Terminal window
# เขียน CPU profile ขณะ benchmark
go test -bench=BenchmarkSearch -cpuprofile=cpu.out ./...
# เขียน heap (memory) profile
go test -bench=BenchmarkSearch -memprofile=mem.out ./...
# เปิด profile ใน interactive pprof tool
go tool pprof cpu.out

เครื่องมือ pprof จะลงลึกในบทเรียน pprof Profiling

ต้องเพิ่ม flag ใดกับ `go test` เพื่อรัน benchmarks?
`b.N` แสดงถึงอะไรใน benchmark function?
Flag ใดที่แสดง memory allocation stats ต่อ operation ใน benchmark output?
ทำไมถึงเรียก b.ResetTimer() ใน benchmark?