Golang周边 | Benchmark性能测试

简介: Golang Benchmark性能测试

前言


基准测试是测量一个程序在固定工作负载下的性能,Go语言也提供了可以支持基准性能测试的benchmark


使用方法


下面展示一个基准测试的示例代码来剖析下它的使用方式:


func Benchmark_test(b *testing.B) {

for i := 0; i < b.N ; i++ {

s := make([]int, 0)

for i := 0; i < 10000; i++ {

  s = append(s, i)

}

}

}


  • 进行基准测试的文件必须以*_test.go的文件为结尾,这个和测试文件的名称后缀是一样的,例如abc_test.go
  • 参与Benchmark基准性能测试的方法必须以Benchmark为前缀,例如BenchmarkABC()
  • 参与基准测试函数必须接受一个指向Benchmark类型的指针作为唯一参数,*testing.B
  • 基准测试函数不能有返回值
  • b.ResetTimer是重置计时器,调用时表示重新开始计时,可以忽略测试函数中的一些准备工作
  • b.N是基准测试框架提供的,表示循环的次数,因为需要反复调用测试的代码,才可以评估性能


命令及参数


性能测试命令为go test [参数],比如go test -bench=. -benchmem,具体的命令参数及含义如下:

参数

含义

-bench regexp

性能测试,支持表达式对测试函数进行筛选。

-bench

. 则是对所有的benchmark函数测试,指定名称则只执行具体测试方法而不是全部

-benchmem

性能测试的时候显示测试函数的内存分配的统计信息

-count n

运行测试和性能多少此,默认一次

-run regexp

只运行特定的测试函数, 比如-run ABC只测试函数名中包含ABC的测试函数

-timeout t

测试时间如果超过t, panic,默认10分钟

-v

显示测试的详细信息,也会把Log、Logf方法的日志显示出来


测试结果


执行命令后,性能测试的结果展示如下


$ go test -bench=. -benchmem

goos: darwin

goarch: amd64

pkg: program/benchmark

cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz

Benchmark_test-12        7439091               152.0 ns/op           248 B/op          5 allocs/op

PASS

ok      promgram/benchmark    1.304s


对以上结果进行逐一分析:

结果项

含义

Benchmark_test-12

Benchmark_test 是测试的函数名 -12 表示GOMAXPROCS(线程数)的值为12

7439091

表示一共执行了7439091次,即b.N的值

152.0 ns/op

表示平均每次操作花费了152.0纳秒

248B/op

表示每次操作申请了248Byte的内存申请

5 allocs/op

表示每次操作申请了5次内存


性能对比实例


下面通过一个数字转换字符串的实例来对比性能测试效果,并进行分析。


//Sprintf

func BenchmarkSprintf(b *testing.B) {

num := 10

b.ResetTimer()

for i := 0; i < b.N; i++ {

fmt.Sprintf("%d", num)

}

}


//Format

func BenchmarkFormat(b *testing.B) {

num := int64(10)

b.ResetTimer()

for i := 0; i < b.N; i++ {

strconv.FormatInt(num, 10)

}

}


//Itoa

func BenchmarkItoa(b *testing.B) {

num := 10

b.ResetTimer()

for i := 0; i < b.N; i++ {

strconv.Itoa(num)

}

}


下面执行命令go test -bench=. -benchmem,收到测试报告如下:


%  go test -bench=. -benchmem

goos: darwin

goarch: amd64

pkg: program/benchmark

cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz

BenchmarkSprintf-12     16364854                63.70 ns/op            2 B/op          1 allocs/op

BenchmarkFormat-12      493325650                2.380 ns/op           0 B/op          0 allocs/op

BenchmarkItoa-12        481683436                2.503 ns/op           0 B/op          0 allocs/op

PASS

ok      program/benchmark    4.007s


可以发现,BenchmarkSprintf方法耗时最长,BenchmarkFormat最快,BenchmarkItoa也很快。差别在于fmt.Sprintf()执行过程中进行了一次内存分配1 allocs/op


结合pprof分析

参数

含义

命令示例

-cpuprofile [file]

输出cpu性能文件

go test -bench=. -benchmem -cpuprofile=cpu.out

-memprofile [file]

输出mem内存性能文件

go test -bench=. -benchmem -memprofile=cpu.out


生成的CPU、内存文件可以通过go tool pprof [file]进行查看,然后在pprof中通过list [file]方法查看CPU、内存的耗时情况


### 内存情况

(pprof) list BenchmarkArrayAppend

Total: 36.49GB

ROUTINE ======================== program/benchmark.BenchmarkArrayAppend in /Users/guanjian/workspace/go/program/benchmark/benchmark_test.go

  11.98GB    11.98GB (flat, cum) 32.83% of Total

        .          .      7://Array

        .          .      8:func BenchmarkArrayAppend(b *testing.B) {

        .          .      9:   for i := 0; i < b.N; i++ {

        .          .     10:           var arr []int

        .          .     11:           for i := 0; i < 10000; i++ {

  11.98GB    11.98GB     12:                   arr = append(arr, i)

        .          .     13:           }

        .          .     14:   }

        .          .     15:}


## CPU情况

(pprof) list BenchmarkArrayAppend

Total: 8.86s

ROUTINE ======================== program/benchmark.BenchmarkArrayAppend in /Users/guanjian/workspace/go/program/benchmark/benchmark_test.go

     10ms      640ms (flat, cum)  7.22% of Total

        .          .      6:

        .          .      7://Array

        .          .      8:func BenchmarkArrayAppend(b *testing.B) {

        .          .      9:   for i := 0; i < b.N; i++ {

        .          .     10:           var arr []int

     10ms       10ms     11:           for i := 0; i < 10000; i++ {

        .      630ms     12:                   arr = append(arr, i)

        .          .     13:           }

        .          .     14:   }

        .          .     15:}


总结


go提供了benchmark性能测试的工具,提供了对函数使用内存、CPU等情况的报告分析,还可以借助pprof获得更好的分析报告等,如果想要深入分析,还可以使用之前介绍的gdb进行底层代码的链路跟踪,以及对代码进行反编译查看具体的性能损耗情况。


参考


go benchmark 性能测试 单元测试 基准测试 使用方法详解
go benchmark 性能测试

相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
相关文章
|
23天前
|
网络协议 安全 测试技术
性能工具之emqtt-bench BenchMark 测试示例
【4月更文挑战第19天】在前面两篇文章中介绍了emqtt-bench工具和MQTT的入门压测,本文示例 emqtt_bench 对 MQTT Broker 做 Beachmark 测试,让大家对 MQTT消息中间 BenchMark 测试有个整体了解,方便平常在压测工作查阅。
123 7
性能工具之emqtt-bench BenchMark 测试示例
|
2月前
|
安全 测试技术 Go
第十五章 Golang单元测试
第十五章 Golang单元测试
23 2
|
4月前
|
测试技术 Go
golang-Mock对单元测试的作用
golang-Mock对单元测试的作用
30 0
|
5天前
|
消息中间件 测试技术 Linux
linux实时操作系统xenomai x86平台基准测试(benchmark)
本文是关于Xenomai实时操作系统的基准测试,旨在评估其在低端x86平台上的性能。测试模仿了VxWorks的方法,关注CPU结构、指令集等因素对系统服务耗时的影响。测试项目包括信号量、互斥量、消息队列、任务切换等,通过比较操作前后的时戳来测量耗时,并排除中断和上下文切换的干扰。测试结果显示了各项操作的最小、平均和最大耗时,为程序优化提供参考。注意,所有数据基于特定硬件环境,测试用例使用Alchemy API编写。
11 0
linux实时操作系统xenomai x86平台基准测试(benchmark)
|
14天前
|
安全 测试技术 Go
Golang深入浅出之-Go语言单元测试与基准测试:testing包详解
【4月更文挑战第27天】Go语言的`testing`包是单元测试和基准测试的核心,简化了测试流程并鼓励编写高质量测试代码。本文介绍了测试文件命名规范、常用断言方法,以及如何进行基准测试。同时,讨论了测试中常见的问题,如状态干扰、并发同步、依赖外部服务和测试覆盖率低,并提出了相应的避免策略,包括使用`t.Cleanup`、`t.Parallel()`、模拟对象和检查覆盖率。良好的测试实践能提升代码质量和项目稳定性。
17 1
|
7月前
|
测试技术 Go
Golang 语言怎么编写测试代码?
Golang 语言怎么编写测试代码?
25 0
|
5月前
|
测试技术 Go
golang 测试模块使用
golang 测试模块使用
31 1
|
5月前
|
NoSQL 测试技术 Linux
Golang 单元测试合集整理,(我最常用 gomonkey)欢迎收藏
Golang 单元测试合集整理,(我最常用 gomonkey)欢迎收藏
|
9月前
|
缓存 NoSQL 测试技术
【Redis】benchmark 测试工具
【Redis】benchmark 测试工具
|
9月前
|
测试技术 Go
Go 单测入门篇:Golang 单元测试基本使用
Go 单测入门篇:Golang 单元测试基本使用