Go语言学习18-基准测试

2023-11-18

引言

所谓基准测试(Benchmark Test,简称BMT)是指,通过一些科学的手段实现对一类测试对象的某项性能指标进行可测量、可重复和可比对的测试。很多时候,基准测试已被狭义地称为性能测试。

基准测试

1. 编写基准测试函数

与功能测试相同,针对其他源码文件中的程序实体的基准测试程序也是以测试函数为单位的。一个基准测试函数的名称和签名如下:

func BenchmarkXxx(b *testing.B)

2. 计时器

在 *testing.B 类型中,与计时器相关的方法有3个它们是 StartTimerStopTimerResetTimer 。这3个方法被用于操纵基准测试函数的计时器。该计时器的作用是计算当前基准测试函数的执行时间。

调用 b.StartTimer 方法意味着开始对当前的测试函数的执行进行计时。它总会在开始执行基准测试函数的时候被自动地调用。这个方法被暴露出来的意义在于:计时器在被停止之后重新启动。调用 b.StopTimer 方法可以使当前测试函数的计时器停止。例如:

package bmt

import (
	"testing"
	"time"
)

func Benchmark(b *testing.B) {
	customTimerTag := false
	if customTimerTag {
		b.StopTimer()
	}
	b.SetBytes(12345678)
	time.Sleep(time.Second)
	if customTimerTag {
		b.StartTimer()
	}
}

如上文件命名为 bmt_test.go 存放到工作区的 testing/bmt 代码包中,运行基准测试截图如下:

这里写图片描述

现在将其中的 customTimerTag 变量的值改为 true ,再来运行测试,截图如下:

这里写图片描述

从上面两个运行截图可以看见最后两行的输出内容不同。在第二个截图中,倒数第二行的3个部分分别代表了当前测试函数的名称,操作次数以及操作平均耗时。其中,操作次数 是当前的基准测试函数被执行的次数,而 操作平均耗时 是当前基准测试函数的平均执行时间。

同样观察两个运行截图的倒数第二行可知,当 customTimerTagtrue 时,基准测试函数 Benchmark 可以被执行多次,而当 customTimerTagfalse 时,它往往只能获得一次执行机会。这些都是由于 testing 包中有这样的一个限制:在基准测试函数单次执行时间超过指定值(默认为1秒,也可以由标记 -benchtime 自定义)的情况下,只执行该基准测试函数一次。也就是测试运行程序会在不超过这个执行时间上限的情况下尽可能多次地执行一个基准测试函数。

customTimerTagtrue 时,在调用语句 time.Sleep(time.Second) 的之前和之后,分别停止和重启了 Benchmark 函数的计时器,这就相当于不把 time.Sleep(time.Second) 语句的执行时间算在 Benchmark 函数的执行时间之内,执行 Benchmark 函数的时间已经基本可以忽略不计了(可以从 0.00 ns/op 可知),这样测试运行程序在 Benchmark 函数的累积执行时间为到达时间上限之前就会连续不断地重复执行它。

customTimerTagfalse 时,调用语句 time.Sleep(time.Second) 让当前的测试程序“休息”1 秒,Benchmark 函数的单次执行时间就肯定会大于 1 秒。因此测试运行程序就不会对 Benchmark 函数执行第二次。

对于方法 b.ResetTimer 在被调用时,会重置当前基准测试函数的计时器,就是把该函数的执行时间重置为 0,这相当于把当前函数中在 b.ResetTimer 语句之前的所有语句的执行时间都从该函数的执行时间中减去。

3. 内存分配统计

方法 b.ReportAllocs 的含义是判断在启动当前测试的 go test 命令的后面是否有 -benchmem 标记。它会返回一个 bool 类型的结果值。

方法 b.SetBytes 接受一个 int64 类型的值,它被用于记录在单次操作中被处理的字节的数量。

customTimerTagfalse,运行截图中,针对 Benchmark 函数的操作信息的那一行信息中多处了一个部分------ 12.34MB/s 。它的含义是每秒被处理的字节的数量(以 MB 为单位)。这个数量其实等于测试运行程序在执行(可能是多次) Benchmark 函数的过程中每秒调用 b.SetBytes 方法的次数乘以传入的那个整数。

首先试想一个场景:在基准测试函数 Benchmark 中测试的是一个向文件系统中写入数据的函数。在写入成功后,会调用 b.SetBytes 方法并把真正写入的字节数作为参数传入。通过测试结果信息中的 xxx MB/s ,可以获知该函数每秒能向文件系统写入多少兆字节( MB )的数据了。

从上面总结,b.SetBytes 方法能够从输入输出(IO)的角度统计出被测试的程序实体的实际性能。

4. 基准测试的运行

在上面的测试中,go test 命令只运行了 cnet/ctcp 包中的功能测试。下面说说 go test 命令的基准测试标记说明。

标记名称 标记描述
-bench regexp 在默认情况下,go test命令不会运行任何基准测试,但可以使用该标记以执行匹配“regexp”处的
正则表达式的基准测试函数,“regexp”可以被替换成任何正则表达式。如果需要运行所有的基准测试函数,
添加 –bench . 或 –bench=. 或 –bench=“.”
-benchmem 在输出内容中包含基准测试的内存分配统计信息
-benchtime t 用来间接地控制单个基准测试函数的操作次数。这里的“t”指的是执行单个测试函数的累积耗时上限。
“t”处的内容使用的是类型time.Duration可接受的时间表示法。“t”的默认值是1s

运行针对代码包 cnet/ctcp 运行基准测试的截图如下:

这里写图片描述

结构体类型 testing.B 的字段 N 可以被用来设置对基准测试函数中的某一个代码块的重复执行次数。例如:

for i := 0; I < b.N; i++ {
	//测试代码
}

运行截图如下:

这里写图片描述

对于计算 N 的值的具体算法,可以查看标准库的 testing 包的源码文件 benchmark.go 中的相关代码。

如果要看到基准测试函数的操作次数和操作平均耗时的同时获得这个过程中的内存分配情况,就需要用到 -benchmem 标记。例如下面截图:

这里写图片描述

23416 B/op”是每次操作分配的字节的平均数为23416个。“109 allocs/op”是每次操作分配内存的次数平均为109次。

go test命令还可以接受一个可自定义测试运行次数并在测试运行期间改变Go语言最大并发处理数的标记 -cpu , -cpu 标记可以是一个整数列表,多个整数之间用逗号分隔。-cpu 标记的处理方式和 -parallel 标记相反,-parallel 标记默认使用Go语言最大并发处理数,而 -cpu 标记却会直接设置它。但是,由 -cpu 标记引发的Go语言最大并发处理数的设置操作并不会影响 -parallel 标记的默认值。因为 -parallel 标记的值是在测试运行程序初始化的时候设置的。如果在 go test 命令中没有显式地加入 -parallel 标记,则它的值会被设置为测试运行程序初始化时刻的Go语言最大并发处理数。在这个时刻,测试程序运行还没有把 -cpu 标记的值(如果有的话)解析成整数数组,也就无法使用这个数组中的整数设置Go语言最大并发处理数了。

使用 -cpu 标记运行截图如下:

这里写图片描述

测试运行程序执行基准测试函数 BenchmarkPrimeFuncs 的次数是 7,这与 -cpu 标记的值 1,2,4,8,12,16,20 中的 7 个数字相对应。上面只是展示了基准测试的运行记录,同样这边也调用了 7 次功能测试函数 TestPrimeFuncs

如上运行截图中,倒数 行的末尾包含了一行运行时环境信息:[GOMAXPROCS=20, NUM_CPU=4, NUM_GOROUTINE=2],对于第一个 GOMAXPROCS 代表Go语言最大并发处理数,此处为 20 , NUM_CPU 代表当前计算机的CPU总内核数,此处为 4NUM_GOROUTINE 代表当前时刻的并发程序的数量,此处为 2

与并发处理有关的标记

标记名称 使用示例 说明
-parallel -parallel 4 功能:设置可并发执行的功能测试函数的最大数量
默认值:调用runtime.GOMAXPROCS(0)后的结果,即Go语言最大并发处理数量
先决条件:功能测试函数需要在开始处调用结构体testing.T类型的参数值的Parallel方法
生效的测试:功能测试
-cpu -cpu 1,2,4 功能:根据标记的值,迭代的设置Go语言并发处理最大数并执行全部功能测试或全部基准测试。
迭代的次数与标记值中的整数个数一致
默认值:“”,即空字符串
先决条件:无
生效的测试:功能测试和基准测试

注意: -cpu-parallel 标记的作用域都是代码包,它们只能用于控制某一个代码包内的测试的流程。如果使用 go test 命令启动了多个代码包的测试,那么每个代码包中的功能测试永远是可并发执行的,而基准测试永远是串行执行的。如果把针对某一个代码包的所有测试的运行过程看成一个整体的话,若在执行 go test 命令时加入了 -bench 标记,则针对各个代码包的测试运行过程会被串行地执行,否则它们将被并发地执行。但无论如何,打印测试记录和结果信息的动作是严格按照 go test 命令后面的代码包从左往右的顺序执行。

结语

本篇介绍了Go语言的基准测试的相关内容,下一篇讲解Go语言的样本测试,敬请期待!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Go语言学习18-基准测试 的相关文章

  • Windows 上Go env 命令设置Go环境变量

    在旧版本中使用下面的命令设置 Enable the go modules feature env GO111MODULE on Set the GOPROXY environment variable env GOPROXY https g
  • 用Go实现的简易TCP通信框架

    接触到GO之后 GO的网络支持非常令人喜欢 GO实现了在语法层面上可以保持同步语义 但是却又没有牺牲太多性能 底层一样使用了IO路径复用 比如在LINUX下用了EPOLL 在WINDOWS下用了IOCP 但是在开发服务端程序的时候 很多都是
  • Sublime Text 3配置Go语言开发环境

    Sublime Text 3配置Go语言开发环境 1 Go语言环境搭建 2 GoSublime安装和配置 2 1 安装步骤 2 2 代码开发 2 3 编译运行 1 Go语言环境搭建 本篇博文是在读者Go自身环境已经搭好 Sublime Te
  • 玩好go的切片

    go的slice 入门就会遇到 但这个东西大多数人都是停留在简单的使用 一些干了好几年的老程序员都说不明白里面的道道 这里面坑不少 恰巧今天有空 好好整理下 永不踩坑 1 为什么要用切片 其他语言大多用的都是数组 在go中 数组的长度是不可
  • 使用 Go API 快速下载 excel 文件

    我们有几个 Golang API 可以为 csvfiles 提供服务 但在提供以编程方式生成的 excel 文件方面没有任何帮助 为了避免重新编写 我们可以借助此服务器开始 main go 这使我们能够服务于路由 和 excel downl
  • Go语言学习19-样本测试

    样本测试 引言 样本测试 1 编写样本测试函数 2 样本测试的运行 3 样本测试函数的命名 结语 引言 上一篇笔者介绍了 Go 语言的 基准测试 其实在测试源码文件中还可以添加样本测试函数 但编写样本测试函数不需要使用 testing 代码
  • 【笔记】Go语言学习笔记

    一 概述 什么是程序 程序 为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的集合 Go语言 是区块链最主流的编程语言 同时也是当前最具发展潜力的语言 Go语言是Google公司创造的语言 也是Google主推的语言 Googl
  • pprof 性能分析

    pprof 是一个强大的性能分析工具 可以捕捉到多维度的运行状态的数据 在程序运行过程中可以获取cpu heap block traces等执行信息 一般情况下使用下列三种pprof分析 runtime pprof 采集程序 非 Serve
  • go语言使用thrift协议实现客户端和服务端报not enough arguments in call to oprot.WriteMessageBegin错误解决方案

    正常步骤 安装golang的Thrift包 go get git apache org thrift git lib go thrift 安装 Thrift 的 IDL 编译工具 http www apache org dyn closer
  • Go语言的JSON 库

    1 Go语言的JSON 库 Go语言自带的JSON转换库为 encoding json 1 1 其中把对象转换为JSON的方法 函数 为 json Marshal 其函数原型如下 func Marshal v interface byte
  • 42-Golang中的单元测试

    Golang中的单元测试 需求 传统方法 基本介绍 单元测试快速入门总结 综合案例 需求 在工作中 我们会遇到这样的情况 就是去确认一个函数 或者一个模块的结果是否正确 传统方法 在main函数中 调用addUpper函数 看看实际输出的记
  • Go Web编程实战(2)----流程控制语句

    目录 流程控制语句 if else语句 for循环语句 用for循环实现do while 用for循环实现while break指定跳出循环 continue语句 for range循环 遍历数组 遍历字符串 遍历map 遍历通道 chan
  • golang 详解协程——errgroup

    为什么要有sync errgroup go支持并发 一般采用的是 channel sync WaitGroup context 来实现各个协程之间的流程控制和消息传递 但是对于开启的成千上万的协程 如果在每个协程内都自行去打印 错误日志的话
  • GoLang学习资源清单

    地鼠文档go语言文档网站通过收集整理go语言相关的学习文档 为大家提供一个学习平台https www topgoer cn 前景 Go语言中文文档https www topgoer com 文档 Gin Web FrameworkGin W
  • 使用Go Hijack和jQuery轻松实现异步推送服务

    使用Go Hijack和jQuery轻松实现异步推送服务 首先要说明的是 这里实现的异步推送服务采用的是Long Polling方式 并不是Comet 如果想用Comet来实现的话 可以参考这个开源项目 http cometd org 不过
  • go语言连接mysql数据库,并验证连通性

    go语言连接mysql数据库 并验证连通性 package main import database sql sql Open加载包 github com go sql driver mysql 没用到包里的内容但是需要加载一下这个包 lo
  • Go语言简介

    一 Go编程语言概述 Go语言也叫Golang 是由谷歌 Google 公司在2007年推出的一款静态编译型语言 主要将其用于服务端开发 并发编程和网络编 程等 1 1 Go语言特性及应用场景 1 容易上手 2 编程速度快 3 原生支持并发
  • Go语言学习9-结构体类型

    结构体类型 引言 1 结构体 1 1 类型表示法 1 2 值表示法 1 3 属性和基本操作 附录 引言 书接上篇 我们了解了Go语言的接口类型 现在介绍Go语言的结构体类型 主要如下 1 结构体 结构体类型既可以包含若干个命名元素 又称字段
  • Golang并发安全和锁

    目录 场景 互斥锁 读写互斥锁 互斥锁 读写锁 Sync Once sync Map 定时器 场景 有时候在Go代码中可能会存在多个goroutine同时操作一个资源 临界区 这种情况会发生竞态问题 数据竞态 类比现实生活中的例子有十字路口
  • go语言教程哪里有?go 语言优秀开源项目汇总

    目录 监控系统 容器技术 PaaS工具 大数据 微服务 CI CD 数据库技术 存储技术 分布式系统 消息系统 服务器管理 安全工具 网络工具 Web工具 Web框架 区块链技术 其它 监控系统 项目 简介 OpenFalcon OpenF

随机推荐

  • JDK8新特性----lambda表达式

    一 Lambda表达式 1 Lambda表达式 注意 函数式接口 接口中只有一个抽象方法 参数1 参数2 抽象方法的参数 gt 分隔符 表示抽象方法的实现 1 lambda基本用法 package com wt practice lx01
  • Java 反射机制(二)

    前言 在上篇 Java 反射机制 一 介绍了一些 Java 反射相关的常用 API 在知道了如何去使用反射之后 作为一个合格的工程师 下一步肯定是要去了解它的如何实现的 我们今天就来看看在 JDK 源码中是如何去实现反射的 PS 以下源码分
  • docker查看mysql日志_如何查看docker运行日志

    查看docker运行日志的方法介绍 docker attach命令 docker attach options 容器会连接到正在运行的容器 然后将容器的标准输入 输出和错误流信息附在本地打印出来 命令中options的取值有三种 detac
  • 护网蓝队(初级)

    护网蓝队 初级 主要是会看各种攻击payload 注意常见的payload 练习各种漏洞的利用方法 学会看利用漏洞的请求长什么样 payload长什么样 payload长什么样 给个请求包 能不能认出来是攻击流量 是的话是什么漏洞的利用 蓝
  • 树09--二叉树的下一个结点

    树09 二叉树的下一个结点 jz57 题目概述 解析 参考答案 注意事项 说明 题目概述 算法说明 给定一个二叉树其中的一个结点 请找出中序遍历顺序的下一个结点并且返回 注意 树中的结点不仅包含左右子结点 同时包含指向父结点的next指针
  • Qt 信号连接多个槽函数 执行顺序

    执行顺序 同一信号连接多个槽呢 槽函数执行没有绝对的先后顺序 如 connect slider QSlider valueChanged spin box QSpinBox setValue connect slider QSlider v
  • 读研期间小论文投稿-个人总结

    我是2014级研究生 学校只是一个普通211 而且工科很弱 导师对我是放养 让我回忆下 上学期就见过她一次 而且她快退休了 没项目没经费没权利 但我觉得跟着她还挺好 因为我可以自己研究自己喜欢的 没人妨碍 但同时导师没有基金 所以我的小论文
  • 两个linux服务器间复制文件

    scp是secure copy的简写 用于在Linux下进行远程拷贝文件的命令 和它类似的命令有cp 不过cp只是在本机进行拷贝不能跨服务器 1 命令格式 scp 参数 原路径 目标路径 2 命令实例 从本地服务器复制到远程服务器 1 复制
  • Vue使用Swiper看这一篇就够了

    Vue使用Swiper看这一篇就够了 此案例实现需求 完成swiper动态异步数据下的slide渲染 自定义分页器样式 解决loop true设置时的事件丢失问题 swiper鼠标移入 移出 暂停 开始轮播 单页面渲染多个swiper组件互
  • 什么是区块链概念

    区块链到底有什么价值 区块链技术被称为价值互联网 大体上原因在于它解决了原有互联网的三个基本问题 第一 区块链通过在数字货币领域的应用 提供了资金流 或者叫资本流 信息在互联网的流动的解决方案 第二 区块链通过加密和分布式账本的引用 解决了
  • 关于Visual Studio 不支持x64 内联汇编分析

    记录一下今天的大坑 实在是有必要记录一下 调程序发现参数在函数传递时 出现了异常的值 已经确认不是指针破坏的问题 用汇编看了下 发现汇编寄存器地址都取错了 在release开启o2优化时出现 关掉又正常 实在是百思不得其解 对于内联汇编 其
  • Mysql根据拼音首字母分组和排序

    最近业务上有个需求 需要根据英文字母展示对应的人名 和我们手机的通讯录差不多 如下图所示 通常如果表设计的时候增加了对应的首字母字段应该很好实现 那如果没加 应该怎么实现呢 图示Sql SELECT name ELT INTERVAL CO
  • Java FileOutputStream类

    文章目录 总结 FileOutputStream类数据结构 FileOutputStream类方法 构造方法 操作方法 总结 FileOutputStream类用于将数据写入文件或文件描述符的输出流 FileOutputStream用于写入
  • 如何查看局域网内所有IP

    要如何查看局域网内正在使用的电脑的IP一共分以下几个步骤 第一步 点击电脑左下角的 开始 然后再点击 运行 第二步 在运行窗口里填入 cmd 然后点击确定 第三步 在cmd命令窗口输入 ipconfig ALL 命令 点击键盘上的回车键 第
  • 2021年字节跳动+京东+美团面试总结!内含福利

    开篇 说一下我大概的情况 渣本毕业 工作已经有快3年了 从高中就开始玩小破站 无论是学习还是日常放松都是在b站 大学主学的软件技术专业 所以 入职bilibili是我大学时期给自己定的小目标 在学校 专业学的算中上的水平 课本知识和老师讲的
  • delphi with do和for do语句

    1 with 对象名 do语句只是为了减少输入的字符 不必每次重复名字 直接写变量 procedure TForm1 Button1Click Sender TObject 正常写法beginedit1 text hello edit1 c
  • J1939协议与CAN2.0对应关系

  • python贪吃蛇小游戏,面向对象设计模式,附带源码以及所需素材

    在python中通过面向对象设计模式来实现一个贪吃蛇小游戏 源码在最下方 上传的资源包内也包括代码源文件以及所需素材等 源文件在game文件夹内 exe文件可直接运行 pygame模块需要自行下载 先来看运行效果图 开始界面 点击按钮开始游
  • Leetcode 括号的分数 -- 栈

    题目描述 leetcode 856 括号的分数 给定一个平衡括号字符串 S 按下述规则计算该字符串的分数 得 1 分 AB 得 A B 分 其中 A 和 B 是平衡括号字符串 A 得 2 A 分 其中 A 是平衡括号字符串 示例 1 输入
  • Go语言学习18-基准测试

    基准测试 引言 基准测试 1 编写基准测试函数 2 计时器 3 内存分配统计 4 基准测试的运行 结语 引言 所谓基准测试 Benchmark Test 简称BMT 是指 通过一些科学的手段实现对一类测试对象的某项性能指标进行可测量 可重复