Golang ---基准测试

 

 

什么是基准测试

基准测试,是一种测试代码性能的方法,好比你有多种不一样的方案,均可以解决问题,那么究竟是那种方案性能更好呢?这时候基准测试就派上用场了。框架

基准测试主要是经过测试CPU和内存的效率问题,来评估被测试代码的性能,进而找到更好的解决方案。好比连接池的数量不是越多越好,那么哪一个值才是最优值呢,这就须要配合基准测试不断调优了。函数

 

如何编写基准测试

基准测试代码的编写和单元测试很是类似,它也有必定的规则,咱们先看一个示例。性能

itoa_test.go单元测试

package gotest

import (
	"fmt"
	"testing"
)

//itoa_test.go
func BenchmarkSprintf(b *testing.B) {
	num := 10
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		fmt.Sprintf("%d", num)
	}
}

  

这是一个基准测试的例子,从中咱们能够看出如下规则:测试

  • 基准测试的代码文件必须以_test.go结尾
  • 基准测试的函数必须以Benchmark开头,必须是可导出的
  • 基准测试函数必须接受一个指向Benchmark类型的指针做为惟一参数
  • 基准测试函数不能有返回值
    b.ResetTimer是重置计时器,这样能够避免for循环以前的初始化代码的干扰
    最后的for循环很重要,被测试的代码要放到循环里
    b.N是基准测试框架提供的,表示循环的次数,由于须要反复调用测试的代码,才能够评估性能
    下面咱们运行下基准测试,看看效果。

 

运行基准测试也要使用go test命令,不过咱们要加上-bench=标记,它接受一个表达式做为参数,匹配基准测试的函数,.表示运行全部基准测试。优化

由于默认状况下go test 会运行单元测试,为了防止单元测试的输出影响咱们查看基准测试的结果,可使用-run=匹配一个历来没有的单元测试方法,过滤掉单元测试的输出,咱们这里使用none,由于咱们基本上不会建立这个名字的单元测试方法。spa

下面着重解释下说出的结果,看到函数后面的-2了吗?这个表示运行时对应的GOMAXPROCS的值。接着的5000000表示运行for循环的次数,也就是调用被测试代码的次数,最后的290 ns/op表示每次须要话费290纳秒。指针

以上是测试时间默认是1秒,也就是1秒的时间,调用5000000次,每次调用花费290纳秒。若是想让测试运行的时间更长,能够经过-benchtime指定,好比3秒。code

能够发现,咱们加长了测试时间,测试的次数变多了,可是最终的性能结果:每次执行的时间,并无太大变化。通常来讲这个值最好不要超过3秒,意义不大。orm

性能对比

上面那个基准测试的例子,实际上是一个int类型转为string类型的例子,标准库里还有几种方法,咱们看下哪一种性能更加。



package gotest

import (
	"fmt"
	"strconv"
	"testing"
)

func BenchmarkSprintf(b *testing.B) {
	num := 10
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		fmt.Sprintf("%d", num)
	}
}

func BenchmarkFormat(b *testing.B) {
	num := int64(10)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		strconv.FormatInt(num, 10)
	}
}

func BenchmarkItoa(b *testing.B) {
	num := 10
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		strconv.Itoa(num)
	}
}

  运行基准测试,看看结果

 

 从结果上看strconv.FormatInt函数是最快的,其次是strconv.Itoa,而后是fmt.Sprintf最慢,前两个函数性能达到了最后一个的10倍多。那么最后一个为何这么慢的,咱们再经过-benchmem找到根本缘由。

 

-benchmem能够提供每次操做分配内存的次数,以及每次操做分配的字节数。allocs/op 表示每次操做从堆上分配内存的次数。B/op 表示每次操做分配的字节数。 从结果咱们能够看到,性能高的两个函数,每次操做都是进行0次内存分配,而最慢的那个要分配2次;性能高的每次操做分配8个字节内存,而慢的那个函数每次须要分配0字节的内存。从这个数据咱们就知道它为何这么慢了,内存分配都占用都过高。
在代码开发中,对于咱们要求性能的地方,编写基准测试很是重要,这有助于咱们开发出性能更好的代码。不过性能、可用性、复用性等也要有一个相对的取舍,不能为了追求性能而过分优化。
相关文章
相关标签/搜索