26.2 基准测试

testing 包中有一些类型和函数可以用来做简单的基准测试;测试代码中必须包含以 BenchmarkZzz 打头的函数并接收一个 *testing.B 类型的参数,比如:

func BenchmarkReverse(b *testing.B) {
    ...
}

命令 go test –test.bench=.* 会运行所有的基准测试函数;代码中的函数会被调用 N 次(N是非常大的数,如 N = 1000000),可以根据情况指定b.N的值,并展示 N 的值和函数执行的平均时间,单位为 ns(纳秒,ns/op)。如果是用 testing.Benchmark 调用这些函数,直接运行程序即可。下面我们看一个测试的具体例子:

package even
func Loop(n uint64) (result uint64) {
	result = 1
	var i uint64 = 1
	for ; i <= n; i++ {
		result *= i
	}
	return result
}
func Factorial(n uint64) (result uint64) {
	if n > 0 {
		result = n * Factorial(n-1)
		return result
	}
	return 1
}

在 even 包的路径下,我们创建一个名为 even_test.go 的测试程序:

package even
import (
	"testing"
)
func TestLoop(t *testing.T) {
	t.Log("Loop:", Loop(uint64(32)))
}
func TestFactorial(t *testing.T) {
	t.Log("Factorial:", Factorial(uint64(32)))
}
func BenchmarkLoop(b *testing.B) {
	for i := 0; i < b.N; i++ {
		Loop(uint64(40))
	}
}
func BenchmarkFactorial(b *testing.B) {
	for i := 0; i < b.N; i++ {
		Factorial(uint64(40))
	}
}

现在我们可以在这个包的目录下使用命令:go test -test.bench=.* 来测试 even 包。输出:

输出:
goos: windows
goarch: amd64
pkg: go42/chapter-13/13.1/1
BenchmarkLoop-4        	50000000	        27.2 ns/op
BenchmarkFactorial-4   	10000000	       163 ns/op
PASS
ok  	go42/chapter-13/13.1/1	3.628s

递归函数的确是很耗费系统资源,而且运行也慢,不建议使用。