欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

关于基准测试(benchmark)

  • Go的标准库内置的testing框架提供了基准测试(benchmark)功能,可以用来验证本地方法在串行或者并行执行时的基准表现,帮助开发者了解代码的真实性能情况,例如一个方法执行一次的平均耗时,还能看到内存分配的情况

关于Go语言基准测试(benchmark)三部曲

  • 《Go语言基准测试(benchmark)三部曲》是欣宸的优异又一些列原创,旨在通过简单的编码实战与大家一同学习和巩固基准测试的常见操作,共分为:基础篇、内存篇、提高篇三部分,每篇都目标明确,用少量代码和命令快速熟悉对应知识点,相信《三部曲》结束后,您也能轻松完成基准测试,根高效的检查代码性能

本篇概览

  • 作为系列的开篇,本文的目标是和大家一起快速开始基准测试,然后将常用的参数和命令都用上一遍,具体步骤如下
  1. 编码,写个本地方法,后面就用benchmark来验证这些方法的性能
  2. 最基本的基准测试
  3. 匹配规则
  4. -cpu参数
  5. -benchtime参数
  6. -count参数
  7. 并行测试

环境信息

  • 操作系统:Windows 11 家庭中文版(22H2),12代i5处理器,16G内存
  • Go:1.19.3
  • VSCode:1.75.1

编码

  • benchmark是用来对已有方法做测试的,因此一开始要把被测试的方法准备好,然后像单元测试那样编写benchmark测试代码,最后用go test做基准测试,咱们这就动手把方法准备好
  • 准备一个目录,名为benchmark-demo,在目录下执行以下命令,新建一个module
go mod init benchmark-demo
  • 用vscode打开此目录,会识别到module,接下来可以在vscode中操作了
  • 新建文件benchmark-demo,里面是用来做基准测试的方法,先写一个简单的方法fib
package main

// 斐波拉契数列
func fib(n int) int {
if n == 0 || n == 1 {
return n
} return fib(n-2) + fib(n-1)
}
  • 接下来就用benchmark来测试fib方法,看看其性能情况

最基本的基准测试

  • 最基本的基准测试是从两个维度去检测方法的性能
  1. 指定时间内,检查方法的运行的耗时
  2. 指定次数,检查方法的运行的耗时
  • 具体操作分为两部
  1. 写benchmark测试方法,就像写单元测试代码一样,代码位于_test.go结尾的文件中
  2. 执行benchmark测试
  • 先来写benchmakr测试方法,新建名为main_test.go,里面有个方法BenchmarkFib,注意要以Benchmark开始,入参是*testing.B类型,这就是最简单的benchmark方法了
func BenchmarkFib(b *testing.B) {
for n := 0; n < b.N; n++ {
fib(30)
}
}
  • 现在用命令行进行测试,执行下面这个最精简的命令,注意:要执行benchmark测试就要带-bench
go test -bench .
  • 很快就完成了基准测试,控制台输出如下,具体含义稍后解释
goos: windows
goarch: amd64
pkg: benchmark-demo
cpu: 12th Gen Intel(R) Core(TM) i5-1240P
BenchmarkFib-16 322 3653937 ns/op
PASS
ok benchmark-demo 1.999s
  • 最前面几行是基本信息, 整理如下
名称 含义
goos 操作系统,这里是windows
goarch CPU架构,这里是64位X86
pkg package名,可以在测试的时候指定package
cpu CPU的信息,这里可以看到是12代酷睿i5
  • 接下来是benchmark的结果,每个数字的具体解释如下图所示

  • benchmark也可以像普通单元测试那样添加验证逻辑的代码,测试结果可以是通过和不通过,BenchmarkFib中没有像普通单元测试那样的失败逻辑,因此最终的判断是测试通过,控制台中输出了PASS
  • 将同样的测试在M1 Pro芯片的Mac Book Pro上运行一遍试试,获取结果如下,可见和前面的windows测试结果大致相近,不同的是结果中没有CPU信息
go test -bench .
goos: darwin
goarch: arm64
pkg: benchmark-demo
BenchmarkFib-8 326 3647077 ns/op
PASS
ok benchmark-demo 1.654s
  • 以上就是最基础的benchmark测试了,咱们已经验证了,接下来试试那些常用的参数

匹配规则

  • 在有多个Benchmark测试方法的时候,如何做到只运行指定的方法呢?
  • 先看指定package的
  1. 指定package:go test -bench benchmark-demo
  2. 指定子package:go test -bench benchmark-demo/XXX
  3. 当前目录下的所有package:go test -bench ./... (斜杠左侧是一个点,右侧是三个点)
  • 再看指定方法的,可以用正则表达式来指定方法名
  1. 所有以Fib结尾的方法:go test -bench='Fib$' benchmark-demo
  2. 所有以BenchmarkNew开始的方法:go test -bench='^BenchmarkNew' benchmark-demo
  • 接下来看几个常用参数

-cpu参数

  • 前面的测试结果BenchmarkFib-16可以看出测试中的GOMAXPROCS等于16,这个值可以用-cpu参数来调整,不过咱们这里不涉及并发编程,GOMAXPROCS的变化对测试结果没有影响,改一下试试,果然没啥波动(稍后还会讲到并行测试,那时候cpu参数的作用就非常明显了)
go test -bench='Fib$' -cpu=2 .
goos: windows
goarch: amd64
pkg: benchmark-demo
cpu: 12th Gen Intel(R) Core(TM) i5-1240P
BenchmarkFib-2 320 3692123 ns/op
PASS
ok benchmark-demo 1.962s

-benchtime参数

  • 前面的命令中我们并没有指定测试时长,因此使用的是默认值1秒,现在咱们来修改这个参数试试,毕竟1秒内完成基准测试并不是普遍适用的
  • 指定基准测试时长为10秒:go test -bench='Fib$' -benchtime=10s benchmark-demo
  • 结果如下
goos: windows
goarch: amd64
pkg: benchmark-demo
cpu: 12th Gen Intel(R) Core(TM) i5-1240P
BenchmarkFib-16 3264 3668947 ns/op
PASS
ok benchmark-demo 12.710s
  • 除了指定时间,还能指定次数,就是指定下图黄色箭头所指的值,也就是控制了被测试方法所执行的次数

  • 指定每轮基准测试内的循环次数为999次:go test -bench='Fib$' -benchtime=999x benchmark-demo
  • 注意将-benchtime的值从10s改为999x,测试范围就从时间变成了次数,测试结果如下,可见准确的执行了999次
go test -bench='Fib$' -benchtime=999x benchmark-demo
goos: windows
goarch: amd64
pkg: benchmark-demo
cpu: 12th Gen Intel(R) Core(TM) i5-1240P
BenchmarkFib-16 999 3667776 ns/op
PASS
ok benchmark-demo 4.006s

-count参数

  • count参数也是用来控制执行次数的,和前面提到的benchtime不同,count用来控制BenchmarkXXX方法的调用次数,而benchtime是用来控制BenchmarkXXX方法的入参b.N的值,如下图所示

  • 指定每轮基准测试内的循环次数为999次,一共两轮:go test -bench='Fib$' -benchtime=999x -count=2 benchmark-demo,输出如下,还是很容易理解的
go test -bench='Fib$' -benchtime=999x -count=2 benchmark-demo
goos: windows
goarch: amd64
pkg: benchmark-demo
cpu: 12th Gen Intel(R) Core(TM) i5-1240P
BenchmarkFib-16 999 3656639 ns/op
BenchmarkFib-16 999 3645846 ns/op
PASS
ok benchmark-demo 7.709s

并行测试

  • 前面的BenchmarkFib是常规的串行测试,如果被测试的方法在真实环境中存在并发调用,那么在基准测试中也应该通过并行测试来了解其基本性能(例如锁造成的阻塞)
  • 为了对fib方法做并行基准测试,需要编写对应的基准测试代码,如下
func BenchmarkParallelFib(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
fib(30)
}
})
}
  • 执行go test -bench='^Benchmark' benchmark-demo,这时BenchmarkFib和BenchmarkParallelFib都会执行,测试结果如下,可见相同时间内,执行fib的总次数是随着并发数量而增加
go test -bench='^Benchmark' benchmark-demo
goos: windows
goarch: amd64
pkg: benchmark-demo
cpu: 12th Gen Intel(R) Core(TM) i5-1240P
BenchmarkFib-16 368 3362756 ns/op
BenchmarkParallelFib-16 3134 370352 ns/op
PASS
ok benchmark-demo 3.189s
  • 通过cpu参数指定GOMAXPROCS数量,执行命令go test -bench='^Benchmark' -cpu=8 benchmark-demo,结果如下,可见串行方法的测试结果没有变化,而并行测试的结果随着GOMAXPROCS的减少有明显下降
go test -bench='^Benchmark' -cpu=8 benchmark-demo
goos: windows
goarch: amd64
pkg: benchmark-demo
cpu: 12th Gen Intel(R) Core(TM) i5-1240P
BenchmarkFib-8 356 3352500 ns/op
BenchmarkParallelFib-8 1989 582177 ns/op
PASS
ok benchmark-demo 3.211s
  • 最后注意,除了cpu参数,前面用过的benchtime和count也都适用于并行测试,含义和串行测试的场景一致
  • 至此,最基本的基准测试已经完成了,下一篇咱们会进行内存相关的基准测试,观察内存的使用和分配情况,敬请期待

欢迎关注博客园:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

Go语言基准测试(benchmark)三部曲之一:基础篇的更多相关文章

  1. 如何系统学习C 语言(上)之 基础篇

    大话C 语言(一) 初识C 语言 老实说,上大学之前我根本不知道什么是C 语言,所以当初学校开设这门课时,我是充满了好奇,所以当初我翻阅了大量的C 语言入门书籍,千篇一律,都是从一些概念.术语和理论讲 ...

  2. C语言----循环结构1(基础篇五)

    今天更新一个C语言的循环,简单点就是就是我们平时在使用电脑时不停的刷新网页,生活中每天都要吃饭等等就是循环,而编程中也有不断循环的过程,或者遇到符合的条件结束循环 下面进入今天的主题: 需求:用计算机 ...

  3. Java语言程序设计与数据结构(基础篇)第七章答案

    答案为本人求解,如有错误,还望海涵.如有雷同,纯属巧合. 7.1 import java.util.Scanner; public class Main { public static void ma ...

  4. java语言程序设计与数据结构(基础篇)第四章答案

    4.1 import java.util.Scanner; public class Welcome { public static void main(String[] args) { Scanne ...

  5. java语言程序设计与数据结构(基础篇)第二章答案

    答案为本人自己求解,若有错误,还望海涵并及时告知.如有雷同,纯属巧合. 2.1 import java.util.Scanner; public class Welcome { public stat ...

  6. [原]Java修炼 之 基础篇(二)Java语言构成

    上次的博文中Java修炼 之 基础篇(一)Java语言特性我们介绍了一下Java语言的几个特性,今天我们介绍一下Java语言的构成.        所谓的Java构成,主要是指Java运行环境的组成, ...

  7. [原]Java修炼 之 基础篇(一)Java语言特性

    学习软件开发,首先要选择的就是选择需要采用的编程语言,考虑语言本身的优缺点和实际需求,综合评价之后选择相关的语言进行系统开发.本篇博客开始就从近年来比较流行的Java开始为大家讲起. 背景 1995年 ...

  8. C语言读取写入CSV文件 [一]基础篇

    本系列文章目录 [一] 基础篇 [二] 进阶篇--写入CSV [三] 进阶篇--读取CSV 什么是CSV? CSV 是一种以纯文本形式存储的表格数据,具体介绍如下(来自维基百科): 逗号分隔值(Com ...

  9. 大数据系列博客之 --- 深入简出 Shell 脚本语言(基础篇)

    首先声明,此系列shell系列博客分为四篇发布,分别是: 基础篇:https://www.cnblogs.com/lsy131479/p/9914747.html 提升篇:https://www.cn ...

  10. C语言----输入输出语句(基础篇二)

    今天整理一下自己的基础篇输入和输出的理解,自己没有研究系统输入和输出函数,以后有时间在去深究,之前在别人的博客里面看到这么一句话分享给大家,“学习就是一个不断抄袭,模仿,练习和创新的一个过程”. 使用 ...

随机推荐

  1. 3D降噪_运动估计块运动匹配

    运动估计 运动估计是视频去噪技术的重要组成之一,计算相邻两帧视频序列各像素的相对运动偏移量,从而得到其运动轨迹. 点 ( i , j ) (i,j) (i,j)和 ( x , y ) (x,y) (x ...

  2. 如何将Maven项目快速改造成一个java web项目(方式一)

    因为实际需要,需要将一个maven项目改造成原生的java-web项目,写这边博客 来记录整个改造的过程.原始的maven项目,使用IDEA打开后,目录结构如下所示 直接通过文件夹查看项目结果如下 首 ...

  3. HTB靶场之Sandworm

    准备: 攻击机:虚拟机kali. 靶机:Sandworm,htb网站:https://www.hackthebox.com/,靶机地址:https://app.hackthebox.com/machi ...

  4. == 与 equals 的区别?

    一. 介绍: Java中的 "=="  是一个运算符,是用于比较两个对象地址值或基本数据类型之间的值是否相等.它的来源可以追溯到C语言,以及受C语言影响的许多其他编程语言. Jav ...

  5. 层叠样式表(CSS)3

    三.层叠样式表属性 1.文字属性 font-size:字体大小 line-height:行高 font-family:字体 font-weight:粗细程度 .......等等很多,可自行学习 2.文 ...

  6. 图加速数据湖分析-GeaFlow和Apache Hudi集成

    表模型现状与问题 关系模型自1970年由埃德加·科德提出来以后被广泛应用于数据库和数仓等数据处理系统的数据建模.关系模型以表作为基本的数据结构来定义数据模型,表为二维数据结构,本身缺乏关系的表达能力, ...

  7. 震惊!强大的接口自动化测试框架2.0,unittest与pytest无缝穿插对接,可以像postman一样编写代码

    theme: fancy highlight: arta 项目介绍 接口自动化测试项目2.0 软件架构 本框架主要是基于 Python + unittest + ddt + HTMLTestRunne ...

  8. [ABC145E] All-you-can-eat

    2023-02-25 题目 题目传送门 翻译 翻译 难度&重要性(1~10):5 题目来源 AtCoder 题目算法 背包dp 解题思路 设 \(dp_i\) 为最后一道菜在第 \(i\) 时 ...

  9. [ABC140E] Second Sum

    2023-02-13 题目 题目传送门 翻译 翻译 难度&重要性(1~10):4 题目来源 AtCoder 题目算法 双向链表 解题思路 \(1.\) 当我们用从小到大的顺序来求解时,把原来求 ...

  10. shopee商品详情接口的应用

    Shopee是东南亚和台湾地区最大的电子商务平台之一,成立于2015年,目前覆盖6个国家和地区.作为一家新兴电商平台,Shopee拥有快速增长的销售额和庞大的用户群体,为开发者提供了丰富的商业机会.其 ...