第17章:性能测试与基准测试
17.1 Go 测试框架
17.1.1 基础测试
go
package database
import "testing"
func TestInit(t *testing.T) {
err := Init("./testdb", false, "", "")
if err != nil {
t.Fatalf("Failed to init database: %v", err)
}
}
func TestQueryRecords(t *testing.T) {
records, err := QueryRecords(Table, "TestDevice", "", "")
if err != nil {
t.Fatalf("Failed to query records: %v", err)
}
t.Logf("Got %d records", len(records))
}
17.1.2 子测试
go
func TestBatchInsert(t *testing.T) {
tests := []struct {
name string
batchSize int
}{
{"small", 10},
{"medium", 100},
{"large", 1000},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
records := generateTestRecords(tt.batchSize)
err := BatchInsertWithRetry(Table, records, 3, time.Second)
if err != nil {
t.Fatalf("Batch insert failed: %v", err)
}
})
}
}
17.2 基准测试
17.2.1 基准测试基础
go
func BenchmarkQueryRecords(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = QueryRecords(Table, "TestDevice", "", "")
}
}
func BenchmarkBatchInsert(b *testing.B) {
records := generateTestRecords(100)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = BatchInsertWithRetry(Table, records, 3, time.Second)
}
}
17.2.2 运行基准测试
bash
# 运行基准测试
go test -bench=. -benchmem
# 运行特定基准测试
go test -bench=BenchmarkQueryRecords -benchmem
# 运行更长时间
go test -bench=. -benchtime=10s -benchmem
17.2.3 基准测试输出解读
BenchmarkQueryRecords-8 10000 123456 ns/op 4567 B/op 12 allocs/op
BenchmarkQueryRecords-8:测试名称和 GOMAXPROCS10000:运行次数123456 ns/op:每次操作纳秒数4567 B/op:每次操作分配字节数12 allocs/op:每次操作分配次数
17.3 性能分析工具
17.3.1 pprof
go
import _ "net/http/pprof"
func main() {
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
// 主程序逻辑
}
bash
# 收集 CPU profile
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
# 收集内存 profile
go tool pprof http://localhost:6060/debug/pprof/heap
# 收集 goroutine profile
go tool pprof http://localhost:6060/debug/pprof/goroutine
17.3.2 pprof 交互命令
top10 # 显示前10个函数
list function # 显示函数代码
web # 生成调用图(需要 graphviz)
png # 生成 PNG 图片
17.3.3 trace 工具
go
import "runtime/trace"
func main() {
f, err := os.Create("trace.out")
if err != nil {
log.Fatal(err)
}
defer f.Close()
trace.Start(f)
defer trace.Stop()
// 主程序逻辑
}
bash
# 运行并生成 trace
go test -trace=trace.out
# 查看 trace
go tool trace trace.out
17.4 负载测试
17.4.1 编写负载测试
go
package main
import (
"net/http"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
client := &http.Client{
Timeout: 10 * time.Second,
}
requestCount := 1000
concurrency := 10
semaphore := make(chan struct{}, concurrency)
startTime := time.Now()
for i := 0; i < requestCount; i++ {
wg.Add(1)
semaphore <- struct{}{}
go func() {
defer wg.Done()
defer func() { <-semaphore }()
resp, err := client.Get("http://localhost:8081/api/readings?deviceName=TestDevice")
if err != nil {
log.Printf("Request failed: %v", err)
return
}
defer resp.Body.Close()
}()
}
wg.Wait()
duration := time.Since(startTime)
log.Printf("Requests: %d", requestCount)
log.Printf("Duration: %v", duration)
log.Printf("RPS: %.2f", float64(requestCount)/duration.Seconds())
}
17.5 实战练习
练习 17.1:基准测试
为数据库模块编写完整的基准测试。
练习 17.2:性能分析
使用 pprof 分析系统瓶颈并优化。
练习 17.3:负载测试
设计并运行负载测试,找出系统最大吞吐量。
17.6 本章小结
本章讲解了性能测试和基准测试:
- Go 测试框架使用
- 基准测试编写和运行
- pprof 性能分析
- trace 工具使用
- 负载测试设计
持续的性能测试是保持系统高性能的关键。
本书版本 :1.0.0
最后更新 :2026-03-08
sfsEdgeStore - 让边缘数据存储更简单!🚀
技术栈 - Go语言、sfsDb与EdgeX Foundry。纯golang工业物联网边缘计算技术栈
项目地址 :GitHub
GitCode 镜像 :GitCode