Golang中如何实现基准测试流水线步骤
Golang中如何实现基准测试流水线步骤 在工作中,拥有一个编译代码并运行单元测试的流水线步骤是相当常见的,否则你的提交就会失败。
是否也有人设置了一个基准测试步骤,对部分代码进行基准测试,以便将当前提交的性能与之前的提交进行比较?
2 回复
关于如何设置一个有什么建议吗?CPU密集型流程 - 我对其进行基准测试,然后我希望每次提交都能看到当前基准测试结果与旧结果的对比 - 有什么想法如何使用GitLab实现这一点吗?
我如何在基准测试流水线步骤的运行之间存储基准测试结果?
更多关于Golang中如何实现基准测试流水线步骤的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Golang中实现基准测试流水线步骤可以通过以下方式实现:
1. 创建基准测试文件
首先,确保你的代码包含基准测试。基准测试文件通常以 _test.go 结尾,并使用 Benchmark 前缀:
// math_ops_test.go
package main
import (
"testing"
)
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(10, 20)
}
}
func BenchmarkMultiply(b *testing.B) {
for i := 0; i < b.N; i++ {
Multiply(10, 20)
}
}
2. 运行基准测试
在流水线中,可以使用以下命令运行基准测试:
# 运行所有基准测试
go test -bench=. -benchmem
# 运行特定包的基准测试
go test ./pkg/calculator -bench=. -benchmem
# 运行匹配模式的基准测试
go test -bench="BenchmarkAdd" -benchmem
# 设置基准测试运行时间(默认1秒)
go test -bench=. -benchtime=5s -benchmem
3. 基准测试流水线脚本示例
创建一个流水线脚本(如 .gitlab-ci.yml 或 GitHub Actions):
# .github/workflows/benchmark.yml
name: Benchmark Tests
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
benchmark:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: '1.19'
- name: Run benchmarks
run: |
go test -bench=. -benchmem -count=5 ./... > benchmark_results.txt
cat benchmark_results.txt
- name: Compare with previous commit
run: |
# 这里可以添加与之前提交的性能比较逻辑
# 例如,使用benchstat工具进行比较
go install golang.org/x/perf/cmd/benchstat@latest
# 获取当前和之前的基准测试结果进行比较
4. 使用benchstat进行性能比较
安装和使用benchstat工具进行性能对比:
# 安装benchstat
go install golang.org/x/perf/cmd/benchstat@latest
# 运行当前提交的基准测试
go test -bench=. -benchmem -count=5 ./... > new.txt
# 切换到之前提交并运行基准测试
git checkout HEAD~1
go test -bench=. -benchmem -count=5 ./... > old.txt
# 比较性能差异
benchstat old.txt new.txt
5. 完整的流水线比较脚本
// tools/benchmark_comparison.go
package main
import (
"fmt"
"os"
"os/exec"
"strings"
)
func main() {
// 获取当前提交哈希
currentCommit := getCommitHash("HEAD")
previousCommit := getCommitHash("HEAD~1")
fmt.Printf("Comparing %s vs %s\n", previousCommit[:8], currentCommit[:8])
// 运行当前提交的基准测试
runBenchmark(currentCommit, "current_bench.txt")
// 运行之前提交的基准测试
runBenchmark(previousCommit, "previous_bench.txt")
// 使用benchstat比较结果
cmd := exec.Command("benchstat", "previous_bench.txt", "current_bench.txt")
output, _ := cmd.Output()
fmt.Println(string(output))
}
func getCommitHash(ref string) string {
cmd := exec.Command("git", "rev-parse", ref)
output, _ := cmd.Output()
return strings.TrimSpace(string(output))
}
func runBenchmark(commit, outputFile string) {
// 切换到指定提交
exec.Command("git", "checkout", commit).Run()
// 运行基准测试
cmd := exec.Command("go", "test", "-bench=.", "-benchmem", "-count=5", "./...")
output, _ := cmd.Output()
os.WriteFile(outputFile, output, 0644)
}
6. 基准测试结果验证
可以在流水线中添加性能阈值检查:
#!/bin/bash
# check_benchmark.sh
# 运行基准测试并解析结果
go test -bench=BenchmarkAdd -benchmem -count=3 ./... | \
grep "ns/op" | \
awk '{print $3}' | \
while read ns; do
# 检查是否超过阈值(例如100ns)
if (( $(echo "$ns > 100" | bc -l) )); then
echo "性能下降:$ns ns/op 超过阈值100 ns/op"
exit 1
fi
done
这种实现方式可以确保每次提交都进行性能基准测试,并与之前的提交进行比较,从而监控性能回归。

