使用golang的基准测试来测试字符串连接性能
基准测试
基准测试主要用来测试CPU和内存的效率问题,来评估被测代码的性能。测试人员可以根据这些性能指标的反馈,来优化我们的代码,进而提高性能问题。
基准测试的使用规则
1.基准测试的代码文件必须以_test.go结尾。
2.基准测试的函数必须以Benchmark开头。
3.基准测试函数必须接受一个指向testing.B类型的指针作为唯一参数。
4.在测试执行之前,需要调用b.ResetTimer(重置计时器)来重置时间,以便过滤掉测试之前代码所消耗的时间。
5.测试代码需要写在for循环中,并且循环中的最大之是b.N。
执行命令时使用的参数
-bench=. :表示的是运行所有的基准测试,. 表示全部。
-benchtime=5s:表示的是运行时间为5s,默认的时间是1s。
-benchmem:表示显示memory的指标。
-run=none:表示过滤掉单元测试,不去跑UT的cases。
具体的例子
我们经常使用“+”来进行字符串的连接,也可以使用bytes.Buffer,那么通过下面这个例子来对比他们之间的差距。
package benchmark
import (
"bytes"
"testing"
"gotest.tools/assert"
)
func TestConcatString(t *testing.T) {
strArray := []string{"a", "b", "c"}
strConcated := ""
for _, str := range strArray {
strConcated += str
}
assert.Equal(t, strConcated, "abc")
}
func BenchmarkConcatStringByBuff(b *testing.B) {
strArray := []string{"a", "b", "c"}
b.StartTimer()
for i := 0; i < b.N; i++ {
var buf bytes.Buffer
for _, str := range strArray {
buf.WriteString(str)
}
}
b.StopTimer()
}
func BenchmarkConcatStringByAdd(b *testing.B) {
elems := []string{"1", "2", "3", "4", "5"}
b.ResetTimer()
for i := 0; i < b.N; i++ {
ret := ""
for _, elem := range elems {
ret += elem
}
}
b.StopTimer()
}
结果分析
goos: darwin
goarch: amd64
pkg: vincent.com/go_leaning/code/benchmark
BenchmarkConcatStringByBuff-4 18462333 61.8 ns/op 64 B/op 1 allocs/op
BenchmarkConcatStringByAdd-4 7628432 159 ns/op 16 B/op 4 allocs/op
- goos: darwin:表示的是操作系统是darwin。
- goarch: amd64:表示目标平台的体系架构是amd64。
- BenchmarkConcatStringByBuff-4;BenchmarkConcatStringByBuff表示运行的函数名称; 4表示的是,运行时对应的GOMAXPROCS的值。
- 18462333:表示的是b.N的在5s内的值。
- 61.8 ns/op:表示执行一次这个函数,消耗的时间是61.8ns。
- 64 B/op:表示每次执行操作,分配64B的内存。
- 1 allocs/op:表示执行一次这个函数,分配内存的次数为1次。
从上面的例子可以明显看出Bytes.Buffer进行字符串连接的性能更高。
参考文章:
https://zhuanlan.zhihu.com/p/267341653
https://zhuanlan.zhihu.com/p/147069299?from_voters_page=true