以斐波那契数列作为测试用例:
package fib
func Fib(n int) int {
switch n {
case 0:
return 0
case 1:
return 1
case 2:
return 2
default:
return Fib(n-1) + Fib(n-2)
}
}
Benchmarkstesting*testing.B*testing.T
方法 | 说明 |
---|---|
Log | 打印日志,同时结束测试 |
Logf | 格式化打印日志,同时结束测试 |
Error | 打印错误日志,同时结束测试 |
Errorf | 格式化打印错误日志,同时结束测试 |
Fatal | 打印致命日志,同时结束测试 |
Fatalf | 格式化打印致命日志,同时结束测试 |
testing.B
fib_test.go
package fib
import (
"testing"
)
func BenchmarkFib20(b *testing.B) {
for n := 0; n < b.N; n++ {
Fib(20) // run the Fib function b.N times
}
}
go test -bench=.
goos: linux
goarch: amd64
BenchmarkFib20-8 50000 37932 ns/op
PASS
Windows 下使用 go test 命令行时,-bench=.应写为-bench="."
-cpuGOMAXPROCS-cpu=1,2,4
$ go test -bench=. -cpu=1,2,4
goos: linux
goarch: amd64
BenchmarkFib20 50000 36877 ns/op
BenchmarkFib20-2 50000 36843 ns/op
BenchmarkFib20-4 30000 36231 ns/op
-benchtime
$ go test -bench=. -benchtime=3s
goos: linux
goarch: amd64
BenchmarkFib20-8 100000 46070 ns/op
PASS
ok _/home/shikanon/study/fib 5.018s
你会发现总的运行时间并不是3s,而且不同的运行其时间会有差异,这主要是因为由于GC活动、后台运行程序、内存位置、CPU的调整频率所影响。
-count
$ go test -bench=. -count=10
goos: linux
goarch: amd64
BenchmarkFib20-8 50000 38395 ns/op
BenchmarkFib20-8 50000 37019 ns/op
BenchmarkFib20-8 50000 36974 ns/op
BenchmarkFib20-8 50000 41050 ns/op
BenchmarkFib20-8 50000 36131 ns/op
BenchmarkFib20-8 30000 37317 ns/op
BenchmarkFib20-8 30000 42872 ns/op
BenchmarkFib20-8 30000 41711 ns/op
BenchmarkFib20-8 50000 36517 ns/op
BenchmarkFib20-8 50000 40240 ns/op
PASS
ok _/home/shikanon/study/fib 20.996s
benchstatbenchstatpref
$benchstat old.txt
name time/op
Fib20-8 39.4µs ±13%
prefgolang/xgit clonebenchstatgo build -o $GOROOT/bin/benchstat main.go
go test -c
./fib2.test -bench=. -test.count=10 > old.txt
./fib.test -bench=. -test.count=10 > new.txt
$ benchstat old.txt new.txt
name old time/op new time/op delta
Fib20-8 44.3µs ± 6% 25.6µs ± 2% -42.31% (p=0.000 n=10+10)
关于 golang 的 for range 的性能比较
for range
package main
import (
"testing"
)
func BenchmarkArray(b *testing.B) {
var a = 0
for i := 0; i < b.N; i++ {
var times [100][0]int
for range times {
a += 1
}
}
}
func BenchmarkInt(b *testing.B) {
var a = 0
for i := 0; i < b.N; i++ {
for i := 0; i < 100; i++ {
a += 1
}
}
}
[100][0]int[0]int
测试结果:
go test -bench=.
goos: windows
goarch: amd64
BenchmarkArray-8 50000000 36.1 ns/op
BenchmarkInt-8 20000000 65.9 ns/op
PASS
for rangefor
切片高效删除指定元素操作
利用了零长切片的特性,实现高效删除技巧:
func TrimSpaceWithAssignment(s []byte) []byte {
var b = make([]byte, len(s))
for i, x := range s {
if x != ' ' {
b[i] = x
}
}
return b
}
func TrimSpaceWithNil(s []byte) []byte {
var b = make([]byte, 0, len(s))
for _, x := range s {
if x != ' ' {
b = append(b, x)
}
}
return b
}
func TrimSpaceWithOrigin(s []byte) []byte {
b := s[:0]
for _, x := range s {
if x != ' ' {
b = append(b, x)
}
}
return b
}
func BenchmarkAssignment(b *testing.B) {
s := []byte("asdf asdf sa fd dsa f d")
for i := 0; i < b.N; i++ {
TrimSpaceWithAssignment(s)
}
}
func BenchmarkNilSlice(b *testing.B) {
s := []byte("asdf asdf sa fd dsa f d")
for i := 0; i < b.N; i++ {
TrimSpaceWithNil(s)
}
}
func BenchmarkOrignSlice(b *testing.B) {
s := []byte("asdf asdf sa fd dsa f d")
for i := 0; i < b.N; i++ {
TrimSpaceWithOrigin(s)
}
}
测试结果:
go test -bench=.
goos: windows
goarch: amd64
BenchmarkAssignment-8 30000000 43.7 ns/op
BenchmarkNilSlice-8 30000000 47.6 ns/op
BenchmarkOrignSlice-8 50000000 22.7 ns/op