怎么写Go基准测试 | 青训营笔记

简介: 怎么写Go基准测试 | 青训营笔记

前言

记录加入青训营的每一天笔记。

或许你经常会思考这样的问题,我用不同的方法实现了同样的效果,哪个会更快?哪个内存消耗更小?这时候你一个简单的基准测试就能解决你的疑惑。

Go向来是以工具丰富而著称的,在学习Go的过程中,你会发现无论是写一个单元测试,还是做一些竞争检测都能很快的上手,而且用的很痛快。当然,接下来要说的基准测试也一样。

基准测试工具就在Go的测试包中,下面就用一个例子来介绍。

举个栗子

由于一些场景需要,我需要将[]byte输出16进制字符。

有时候我会这么写:

fmt.Sprintf("%x", b)

但有时候我会这么写:

hex.EncodeToString(b)

但到底哪种写法更好呢?今天我就来比较一下。

直接写了个main.go

func EncodeA(b []byte) string {
    return fmt.Sprintf("%x", b)
}
func EncodeB(b []byte) string {
    return hex.EncodeToString(b)
}

再写个测试main_test.go

var buf = []byte("skdjadialsdgasadasdhsakdjsahlskdjagloqweiqwo")
func BenchmarkEncodeA(b *testing.B) {
    for i := 0; i < b.N; i++ {
        EncodeA(buf)
    }
}
func BenchmarkEncodeB(b *testing.B) {
    for i := 0; i < b.N; i++ {
        EncodeB(buf)
    }
}

就这么简单,我们的基本测试就写完了。从我的写法中你也许就知道:

  • 和单元测试一样,都写在_test.go文件中;
  • 需要以Benchmark为函数名开头;
  • 和单元测试类似,必须接受一个*testing.B参数;
  • 被测试代码放在一个循环中。

我们直接跑一下。当然我们也是用go test来执行测试,简单的测试只要带上-bench=.就可以了。

$ go test -bench=.
goos: darwin
goarch: amd64
pkg: github.com/razeencheng/demo-go/benchmark
BenchmarkEncodeA-8       5000000               265 ns/op
BenchmarkEncodeB-8      10000000               161 ns/op
PASS
ok      github.com/razeencheng/demo-go/benchmark        3.397s

前两行是平台信息,第三行包名。第四、五行就是测试的结果了。

  • BenchmarkEncodeA-8 ,BenchmarkEncodeB-8 基准测试函数名-GOMAXPROCS
  • 5000000,10000000 被测试的函数执行次数,也就是EncodeA()被执行了5000000次,EncodeB()被执行了10000000次,也就是b.N的值了。
  • 265 ns/op,161 ns/op表示每次调用被测试函数花费的时间。

从花费的时间上来看,我们知道EncodeB()要快一点。

更多

你以为就这么简单的结束了么?NONONO。

  • -bench 可接收一个有效的正则表达式来执行符合条件的测试函数。当你的函数很多时,可以用它来过滤.
$ go test -bench=BenchmarkEncodeA
goos: darwin
goarch: amd64
pkg: github.com/razeencheng/demo-go/benchmark
BenchmarkEncodeA-8       5000000               256 ns/op
PASS
ok      github.com/razeencheng/demo-go/benchmark        1.575s
  • -benchmem可以查看内存分配
$ go test -bench=. -benchmem
goos: darwin
goarch: amd64
pkg: github.com/razeencheng/demo-go/benchmark
BenchmarkEncodeA-8       5000000               261 ns/op             128 B/op          2 allocs/op
BenchmarkEncodeB-8      10000000               162 ns/op             192 B/op          2 allocs/op
PASS
ok      github.com/razeencheng/demo-go/benchmark        3.408s

其中B/op 表示每次执行会分配多少内存,allocs/op表示每次执行会发生多少次内存分配。

  • -benchtime指定每个测试执行的时间。默认1s,当你的函数比较耗时你可以设置更长一点。因为b.N是与这个时间有关的。
    当你的运行时间没达到-benchtime制定的时间前,b.N将以1,2,5,10,20,50…增加,然后重新运行测试代码。
$ go test -bench=. -benchmem -benchtime=5s
goos: darwin
goarch: amd64
pkg: github.com/razeencheng/demo-go/benchmark
BenchmarkEncodeA-8      30000000               254 ns/op             128 B/op          2 allocs/op
BenchmarkEncodeB-8      50000000               160 ns/op             192 B/op          2 allocs/op
PASS
ok      github.com/razeencheng/demo-go/benchmark        16.113s
  • -count指定每个测试执行的次数。
$ go test -bench=. -benchmem -count=3
goos: darwin
goarch: amd64
pkg: github.com/razeencheng/demo-go/benchmark
BenchmarkEncodeA-8       5000000               256 ns/op             128 B/op          2 allocs/op
BenchmarkEncodeA-8       5000000               255 ns/op             128 B/op          2 allocs/op
BenchmarkEncodeA-8       5000000               253 ns/op             128 B/op          2 allocs/op
BenchmarkEncodeB-8      10000000               163 ns/op             192 B/op          2 allocs/op
BenchmarkEncodeB-8      10000000               160 ns/op             192 B/op          2 allocs/op
BenchmarkEncodeB-8      10000000               160 ns/op             192 B/op          2 allocs/op
PASS
ok      github.com/razeencheng/demo-go/benchmark        9.984s

我常用的也就这些了。

但对于testing.B来说,它拥有了testing.T的全部接口,所以Fail,Skip,Error这些都可以用,而且还增加了

  • SetBytes( i uint64) 统计内存消耗。
  • SetParallelism(p int) 制定并行数目。
  • StartTimer / StopTimer / ResertTimer 操作计时器。

你可以按需使用。r

注意

b.N为一个自增字段,谨慎用它做函数参数。

目录
相关文章
|
21小时前
|
机器人 定位技术 C++
技术笔记:ROS中测试机器人里程计信息
技术笔记:ROS中测试机器人里程计信息
|
2天前
|
测试技术 Go
go的测试编写、断言、性能测试
go的测试编写、断言、性能测试
5 0
|
30天前
|
JSON 自然语言处理 网络协议
【字节跳动青训营】后端笔记整理-2 | Go实践记录:猜谜游戏,在线词典,Socks5代理服务器
猜数字游戏也算是入门一门编程语言必写的程序了。通过这个程序,我们可以熟悉Go语言中的输入输出、流程控制与随机函数的调用。
37 2
|
30天前
|
IDE 测试技术 Go
【字节跳动青训营】后端笔记整理-3 | Go语言工程实践之测试
用于验证已经修改或新增功能后,软件的既有功能是否受到影响。
69 2
|
30天前
|
存储 关系型数据库 MySQL
|
30天前
|
Java 编译器 Go
【字节跳动青训营】后端笔记整理-1 | Go语言入门指南:基础语法和常用特性解析(一)
本文主要梳理自第六届字节跳动青训营(后端组)-Go语言原理与实践第一节(王克纯老师主讲)。
48 1
|
14天前
|
移动开发 测试技术 C语言
Python基础教程(第3版)中文版 第16章 测试基础(笔记)
Python基础教程(第3版)中文版 第16章 测试基础(笔记)
|
30天前
|
存储 JSON Java
【字节跳动青训营】后端笔记整理-1 | Go语言入门指南:基础语法和常用特性解析(三)
在 Go 语言里,符合语言习惯的做法是使用一个单独的返回值来传递错误信息。
32 0
|
30天前
|
存储 Go C++
【字节跳动青训营】后端笔记整理-1 | Go语言入门指南:基础语法和常用特性解析(二)
Go 语言中的复合数据类型包括数组、切片(slice)、映射(map)和结构体(struct)。
46 0
|
5天前
|
安全 测试技术 Go
Go语言在高并发场景下的应用
在当今互联网高速发展的时代,高并发已成为众多应用系统面临的核心问题。本文探讨了Go语言在高并发场景下的优势,并通过具体实例展示了其在实际应用中的效果和性能表现。