企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## Banchmark 用法: ~~~ func BenchmarkExample(b *testing.B) { // 与性能测试无关的代码 b.ResetTimer() for i := 0; i < b.N; i++ { // 测试代码 fmt.Println("hello") } b.StopTimer() // 与性能测试无关的代码 } ~~~ 示例: go test -bench=. go test -bench=. -benchmem ~~~ // 测试直接拼接字符串 func BenchmarkJoinString(b *testing.B) { str := []string{"php", "nodejs", "java", "go", "c"} b.ResetTimer() for i := 0; i < b.N; i++ { result := "" for _, v := range str { result += v } } b.StopTimer() } func BenchmarkBufferWriteString(b *testing.B) { str := []string{"php", "nodejs", "java", "go", "c"} b.ResetTimer() for i := 0; i < b.N; i++ { var buf bytes.Buffer for _, v := range str { buf.WriteString(v) } } b.StopTimer() } output=> 方法 运行次数 平均耗时 内存占用 内存操作次数 BenchmarkJoinString-8 7218064 157 ns/op 64 B/op 4 allocs/op BenchmarkBufferWriteString-8 17479418 61.4 ns/op 64 B/op 1 allocs/op ~~~ ### 并行测试 func (b*B) RunParallel(body func(*PB))会以并行的方式执行给定的基准测试。 RunParallel会创建出多个goroutine,并将b.N分配给这些goroutine执行, 其中goroutine数量的默认值为GOMAXPROCS。用户如果想要增加非CPU受限(non-CPU-bound)基准测试的并行性, 那么可以在RunParallel之前调用SetParallelism 。RunParallel通常会与-cpu标志一同使用。 ~~~ func BenchmarkSplitParallel(b *testing.B) { // b.SetParallelism(1) // 设置使用的CPU数 b.RunParallel(func(pb *testing.PB) { for pb.Next() { Split("枯藤老树昏鸦", "老") } }) } ~~~ 执行一下基准测试: ~~~ split $ go test -bench=. goos: darwin goarch: amd64 pkg: github.com/pprof/studygo/code_demo/test_demo/split BenchmarkSplit-8 10000000 131 ns/op BenchmarkSplitParallel-8 50000000 36.1 ns/op PASS ok github.com/pprof/studygo/code_demo/test_demo/split 3.308s ~~~ 还可以通过在测试命令后添加-cpu参数如go test -bench=. -cpu 1来指定使用的CPU数量 ### TestMain 通过在`*_test.go`文件中定义TestMain函数来可以在测试之前进行额外的设置(setup)或在测试之后进行拆卸(teardown)操作。 如果测试文件包含函数:`func TestMain(m *testing.M)`那么生成的测试会先调用 TestMain(m),然后再运行具体测试。TestMain运行在主goroutine中, 可以在调用 m.Run前后做任何设置(setup)和拆卸(teardown)。退出测试的时候应该使用m.Run的返回值作为参数调用os.Exit。 一个使用TestMain来设置Setup和TearDown的示例如下: ~~~ func TestMain(m *testing.M) { fmt.Println("write setup code here...") // 测试之前的做一些设置 // 如果 TestMain 使用了 flags,这里应该加上flag.Parse() retCode := m.Run() // 执行测试 fmt.Println("write teardown code here...") // 测试之后做一些拆卸工作 os.Exit(retCode) // 退出测试 } ~~~ 需要注意的是:在调用TestMain时, flag.Parse并没有被调用。所以如果TestMain 依赖于command-line标志 (包括 testing 包的标记), 则应该显示的调用flag.Parse