• GO基准测试


    基准测试就是在一定的工作负载之下检测程序性能的一种方法

    基准测试用例约定

    • 基准测试以Benchmark为前缀
    • 需要一个*testing.B类型的参数b
    • 基准测试必须要执行b.N次

    testing.B的拥有的方法如下:

    func (c *B) Error(args ...interface{})
    func (c *B) Errorf(format string, args ...interface{})
    func (c *B) Fail()
    func (c *B) FailNow()
    func (c *B) Failed() bool
    func (c *B) Fatal(args ...interface{})
    func (c *B) Fatalf(format string, args ...interface{})
    func (c *B) Log(args ...interface{})
    func (c *B) Logf(format string, args ...interface{})
    func (c *B) Name() string
    func (b *B) ReportAllocs()
    func (b *B) ResetTimer()
    func (b *B) Run(name string, f func(b *B)) bool
    func (b *B) RunParallel(body func(*PB))
    func (b *B) SetBytes(n int64)
    func (b *B) SetParallelism(p int)
    func (c *B) Skip(args ...interface{})
    func (c *B) SkipNow()
    func (c *B) Skipf(format string, args ...interface{})
    func (c *B) Skipped() bool
    func (b *B) StartTimer()
    func (b *B) StopTimer()
    

    动手环节

    编写基准测试代码

    // fib.go
    package main
    
    import "fmt"
    
    func fib(n int) int {
    	if n == 0 || n == 1 {
    		return n
    	}
    	return fib(n-2) + fib(n-1)
    }
    
    func main() {
    	fmt.Println(fib(10))
    }
    
    // fib_test.go
    package main
    
    import "testing"
    
    func BenchmarkFib(b *testing.B) {
    	for n := 0; n < b.N; n++ {
    		fib(30)
    	}
    }
    
    // 测试
    go test -bench=Fib -run=none
    go test -bench=Fib -run=none -benchmem
    go test -benchmem -bench=. -run=none
    

    测试命令

    $ go test -bench=Fib
    goos: windows
    goarch: amd64
    pkg: test
    BenchmarkFib-8               228           5253644 ns/op   
    PASStest
    ok    test  1.785s
    
    // 结果解析
    BenchmarkFib-8 表示对Fib函数进行基准测试,数字8表示 GOMAXPROCS 的值
    5253644 ns/op  表示每次调用Fib函数耗时5253644ns
    228            这是228次调用的平均值
    

    -benchmem 参数展示内存消耗情况

    $ go test -bench=Fib -benchmem
    goos: windows
    goarch: amd64
    pkg: test
    BenchmarkFib-8               198           6503562 ns/op               0 B/op          0 allocs/op   
    PASStest
    ok    test  1.785s
    
    // 结果解析
    0 B/op       表示每次操作内存分配了0字节
    0 allocs/op  表示每次操作进行了0次内存分配
    

    -cpu 不同核心cpu结果

    go test -bench=Fib -cpu=1 -benchmem 
    

    -count 连续跑N次

    go test -bench=Fib -count=10 -benchmem
    

    -benchtime 指定运行秒数

    go test -bench=Fib -benchtime=10s -benchmem
    

    问题:-run=none参数有什么用?

    go test -bench=Fib -run=none   // 结果?
    

    测试函数传参-性能测试

    很多性能问题是发生在两个不同操作之间的相对耗时,比如同一个函数处理1000个元素的耗时与处理10000甚至100000个元素的耗时的差别是多少?

    再或者对于同一个任务究竟使用哪种算法性能最佳?

    我们通常需要对两个不同算法的实现使用相同的输入来进行基准比较测试

    package main
    
    import (
    	"testing"
    )
    
    func Add(n int) int {
    	tmp := 0
    	for i := 0; i <= n; i++ {
    		tmp = tmp + i
    	}
    	return tmp
    }
    
    func benchmarkAdd(i int, b *testing.B) {
    	for n := 0; n < b.N; n++ {      // b.N你觉得是什么
    		Add(i)
    	}
    }
    
    func BenchmarkAdd1000(b *testing.B)   { benchmarkAdd(1000, b) }
    func BenchmarkAdd10000(b *testing.B)  { benchmarkAdd(10000, b) }
    func BenchmarkAdd100000(b *testing.B) { benchmarkAdd(100000, b) }
    

    bench测试

    $ go test -bench=.
    goos: linux
    goarch: amd64
    pkg: test
    cpu: Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
    BenchmarkGenerate1000-8          3997779               303.6 ns/op
    BenchmarkGenerate10000-8          402241              2889 ns/op
    BenchmarkGenerate100000-8          42884             28545 ns/op
    PASS
    ok      test    4.225s
    
    // 默认情况下,每个基准测试至少运行1秒。如果在Benchmark函数返回时没有到1秒,则b.N的值会按1,2,5,10,20,50,…增加,并且函数再次运行。
    

    -benchtime标志增加最小基准时间,以产生更准确的结果

    $ go test -bench=. -benchtime=20s
    goos: linux
    goarch: amd64
    pkg: test
    cpu: Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
    BenchmarkAdd1000-8      81030480               293.2 ns/op
    BenchmarkAdd10000-8      8304865              2848 ns/op
    BenchmarkAdd100000-8      846728             28599 ns/op
    PASS
    ok      test    75.148s
    

    b.ResetTimer-重置时间:一般加在不计划作为测试报告的操作之后

    func benchmarkAdd(i int, b *testing.B) {
    	time.Sleep(1 * time.Second)
    	b.ResetTimer() // -----------------例子-------------------
    	for n := 0; n < b.N; n++ { 
    		Add(i)
    	}
    }
    

    b.SetParallelism()-设置使用CPU数 // 加了实际没生效 go1.16版本 linux环境 建议使用命令行参数 -cpu=n

    func benchmarkAdd(i int, b *testing.B) {
    	b.SetParallelism(2) // -----------------例子-------------------
    	for n := 0; n < b.N; n++ { 
    		Add(i)
    	}
    }
    

    b.RunParallel()-并行测试:创建出多个goroutine,goroutine数量默认为 GOMAXPROCS 数量也就是CPU核数

    // 例子
    func benchmarkAdd(i int, b *testing.B) {
    	b.RunParallel(func(pb *testing.PB) {
    		for pb.Next() {
    			Add(i)
    		}
    	})
    }
    
    // SetParallelism() 加了实际没生效 go1.16版本 linux环境
    func benchmarkAdd(i int, b *testing.B) {
    	b.SetParallelism(1)
    	b.RunParallel(func(pb *testing.PB) {
    		for pb.Next() {
    			Add(i)
    		}
    	})
    }
    
    // -cpu
    go test -bench=. -cpu=1
    go test -bench=. -cpu=2
    go test -bench=. -cpu=4
    go test -bench=. -cpu=8
    
  • 相关阅读:
    ↗☻【精彩绝伦的CSS#BOOK#】
    Adding client to server's list failed, CORBA error: IDL:omg.org/CORBA/COMM_FAILURE:1.0
    hadoop文件输出控制,多路径输出到不同文件
    virtualbox安装CentOS无法上网
    ant如何使用——初学者一篇通
    linux下用户命令
    hadoop启动后进safemode不出来
    hadoop获取context的当前输出路径,
    hadoop输出控制,输出到指定文件中
    python option.parser
  • 原文地址:https://www.cnblogs.com/Otiger/p/16221889.html
Copyright © 2020-2023  润新知