当前位置: 首页 > news >正文

Go语言测试第二弹——基准测试

在前一篇文章中,我们讲解了Go语言中最基础的单元测试,还没有看过的可以自行去查看,这篇文章我们详细了解Go语言里面的基准测试。

基准测试

基准测试,也就是BenchmarkTest,基准测试是用来测试代码性能的的一种方法,使用基准测试时,测试函数必须以Benchmark开头,后面跟具体需要测试的函数的名称,基本格式如下:

// Add函数对应的基准测试函数
func BenchmarkAdd(b *testing.B){}

基准测试函数中的参数是b *testing.B,基准测试时函数必须要执行b.N次,只有这样测试才能具有参考性和一定的准确性。b.N这个值并不是固定的,而是根据情况变化,从1开始,如果当前测试函数能够在1秒内执行完毕,则会将b.N的值增加到2,如果测试函数同样在1秒内执行完毕,则会继续增加b.N的值,b.N的递增序列为1,2,3,5,10,20,30,50,100

基本使用

现在我们先写一个计算斐波拉契数列的函数:

// Fib 递归函数计算斐波拉契数列的第 x 个数
func Fib(x int) int {if x <= 1 {return x}return Fib(x-1) + Fib(x-2)
}

然后在对应的测试文件中写上针对Fib函数的基准测试函数:

func BenchmarkFib(b *testing.B) {for i := 0; i < b.N; i++ {Fib(10)}
}

在功能函数和基准测试函数都准备完毕之后我们可以使用go test命令来执行对应的基准测试,使用该命令不能直接运行基准测试,需要在参数后面指定-bench参数并指定响应的函数名称。

PS C:\Users\lee\GolandProjects\test\calc> go test -bench=Fib
goos: windows
goarch: amd64
pkg: test/calc
cpu: Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
BenchmarkFib-8           4861580               235.1 ns/op
PASS
ok      test/calc       1.567s

上面的输出中,上面都是一些系统相关信息,下面BenchmarkFib-8后面的数字表示的是GOMAXPROCS,默认等于CPU的核数,后面的4861580235.1 ns/op表示当前测试用例执行的4861580次,平均花费时间为235.1 ns,总耗时为1.567s
在使用的时候还可以通过其他参数来获取更多的测试数据,用来提升测试的准确率和可参考性。
使用-benchmem参数来获取内存分配的数据。

PS C:\Users\lee\GolandProjects\test\calc> go test -bench=Fib -benchmem
goos: windows
goarch: amd64
pkg: test/calc
cpu: Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
BenchmarkFib-8           4749666               251.0 ns/op             0 B/op          0 allocs/op
PASS
ok      test/calc       1.609s

在耗时的后面新增了0 B/op0 allocs/op,其中0 B/op表示每次运行测试分配了0B的内存,0 allocs/op表示每次运行测试进行了0次的内存分配,因为我们的功能函数没用到额外的内存,所以这两个值都是0,大家可以自己尝试其他方法来看看这个值的变化。
使用-benchtime参数指定测试的基准时间或次数,在前面我们说过测试用例会执行b.N次,这个数量是动态变化的,只要运行测试用例的时间没有超过1秒就会递增这个值。现在可以使用-benchtime参数指定这个基准时间,如果修改为5,可以使用-benchtime=5s,则表示执行时间不超过5秒,就会递增b.N

PS C:\Users\lee\GolandProjects\test\calc> go test -bench=Fib -benchtime=5s
goos: windows
goarch: amd64
pkg: test/calc
cpu: Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
BenchmarkFib-8          23184202               235.6 ns/op
PASS
ok      test/calc       5.859s

通过上面的输出可以看到,一共运行了23184202次,平均每次耗时235.6 ns,总耗时5.859s。因为通过-benchtime指定了基准时间为5秒,所以总运行次数大概是之前的5倍。
-benchtime除了指定时间之外,还可以用来指定具体的次数,假设指定执行100次,可以使用-benchtime=100x

PS C:\Users\lee\GolandProjects\test\calc> go test -bench=Fib -benchtime=100x
goos: windows
goarch: amd64
pkg: test/calc
cpu: Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
BenchmarkFib-8               100               487.0 ns/op
PASS
ok      test/calc       0.167s

上面可以看到通过-benchtime指定次数后,一共调用了Fib函数100次,总耗时0.167s
-count参数可以用来指定测试的轮数,比如指定执行3轮。

PS C:\Users\lee\GolandProjects\test\calc> go test -bench=Fib -count=3       
goos: windows
goarch: amd64
pkg: test/calc
cpu: Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
BenchmarkFib-8           4641591               261.0 ns/op
BenchmarkFib-8           5031808               238.0 ns/op
BenchmarkFib-8           5103565               245.1 ns/op

性能比较

在基准测试中,某些功能函数在不同的输入时,相对应的性能也会有所差别,在前面的所有测试中,我们传递的参数都是10,也就是每次都计算的是斐波拉契数列的第10个,如果我们需要测试一个函数在不同的输入下的性能差异,或者是测试两个函数在相同输入下的性能差异,就会使用到性能比较的测试方法,在比较性能的时候就需要使用到一个带参数的测试函数,再使用其他的Benchmark函数传入不同的值来调用,用以测试不同输入的性能差别。
我们将上面的测试代码修改如下:

func benchmarkFib(b *testing.B, n int) {for i := 0; i < b.N; i++ {Fib(n)}
}func BenchmarkFib2(b *testing.B) {benchmarkFib(b, 2)
}func BenchmarkFib10(b *testing.B) {benchmarkFib(b, 10)
}func BenchmarkFib20(b *testing.B) {benchmarkFib(b, 20)
}func BenchmarkFib30(b *testing.B) {benchmarkFib(b, 30)
}

在代码中写了一个带有参数的辅助函数benchmarkFib,可以传入参数,并且构造了4个测试用例,分别传入不同的参数,执行上面的测试用例。

PS C:\Users\lee\GolandProjects\test\calc> go test -bench=Fib
goos: windows
goarch: amd64
pkg: test/calc
cpu: Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz
BenchmarkFib2-8         304879520                3.793 ns/op
BenchmarkFib10-8         5249786               232.8 ns/op
BenchmarkFib20-8           41760             28409 ns/op
BenchmarkFib30-8             345           3571588 ns/op
PASS
ok      test/calc       6.245s

可以看到,在不同的输入下,函数的执行次数和平均执行时间都有不小的差距,当计算第30个数的时候一共才执行了345次,而每次的平均执行时间为3571588 ns

重置时间

在进行基准测试的时候,通常都是用来测试函数的性能,我们上面的函数都是简单的一些示例,但是在日常的工作中,我们测试之前可能需要有一些准备工作,例如测试前读取文件,这样的话在测试的时候就会将读取文件的耗时也计算到测试报告里面去,这个时候我们可以使用到ResetTimer来重置时间,代码如下:

func BenchmarkFib(b *testing.B) {// sleep 3秒,模拟测试前的准备工作time.Sleep(time.Second * 3)// 重置定时器b.ResetTimer()for i := 0; i < b.N; i++ {Fib(10)}
}

在代码中调用了b.ResetTimer()方法,这样就表示重置定时器,意味着这行代码之前的所有代码的耗时都不会被计算到测试中,这样能够确保代码测试的准确性。

相关文章:

Go语言测试第二弹——基准测试

在前一篇文章中&#xff0c;我们讲解了Go语言中最基础的单元测试&#xff0c;还没有看过的可以自行去查看&#xff0c;这篇文章我们详细了解Go语言里面的基准测试。 基准测试 基准测试&#xff0c;也就是BenchmarkTest&#xff0c;基准测试是用来测试代码性能的的一种方法&…...

关于“刘亦菲为什么无人敢娶”的问题❗❗❗

关于“刘亦菲为什么无人敢娶”的问题&#xff0c; 实际上涉及到多个方面的因素&#xff0c; 以下是对这些因素的详细分析&#xff1a;1.事业心重&#xff1a;刘亦菲作为华语影视圈的知名女星&#xff0c;她的演艺事业非常成功&#xff0c; 这也意味着她将大量的时间和精力投…...

LeetCode:经典题之141、142 题解及延伸

系列目录 88.合并两个有序数组 52.螺旋数组 567.字符串的排列 643.子数组最大平均数 150.逆波兰表达式 61.旋转链表 160.相交链表 83.删除排序链表中的重复元素 389.找不同 1491.去掉最低工资和最高工资后的工资平均值 896.单调序列 206.反转链表 92.反转链表II 141.环形链表 …...

rk3568 OpenHarmony 串口uart与电脑通讯开发案例

一、需求描述&#xff1a; rk3568开发板运行OpenHarmony4.0&#xff0c;通过开发板上的uart串口与电脑进行通讯&#xff0c;相互收发字符串。 二、案例展示 1、开发环境&#xff1a; &#xff08;1&#xff09;rk3568开发板 &#xff08;2&#xff09;系统&#xff1a;OpenHar…...

canvas画布旋转问题

先说一下为什么要旋转的目的&#xff1a;因为在画布上签名&#xff0c;在不同的设备上我需要不同方向的签名图片&#xff0c;电脑是横屏&#xff0c;手机就是竖屏&#xff0c;所以需要把手机的签名旋转270&#xff0c;因此写了这个方法。 关于画布旋转的重点就是获取到你的画布…...

vue3 【提效】自动导入框架方法 unplugin-auto-import 实用教程

是否还在为每次都需要导入框架方法而烦恼呢&#xff1f; // 每次都需手动导入框架方法 import { ref } from vuelet num ref(0)用 unplugin-auto-import 来帮你吧&#xff0c;以后只需这样写就行啦&#xff01; let num ref(0)官方示例如下图 使用流程 1. 安装 unplugin-au…...

clip系列改进Lseg、 group ViT、ViLD、Glip

Lseg 在clip后面加一个分割head&#xff0c;然后用分割数据集有监督训练。textencoder使用clip&#xff0c;frozen住。 group ViT 与Lseg不同&#xff0c;借鉴了clip做了真正的无监督学习。 具体的通过group block来做的。使用学习的N个group token&#xff08;可以理解为聚类…...

Ubuntu下TensorRT与trtexec工具的安装

新版&#xff08;这里测试的是10.1版&#xff09;的onnx转tensorrt engine工具trtexec已经集成在TensorRT中&#xff0c;不需要额外单独安装。 教程来源于此网页&#xff1a;https://medium.com/moshiur.faisal01/install-tensorrt-with-command-line-wrapper-trtexec-on-unun…...

MySQL定时任务

事件调度器操作 查看事件调度器是否开启&#xff1a;ON 表示已开启。 show variables like %event_scheduler%; ------------------------ | Variable_name | Value | ------------------------ | event_scheduler | ON | ------------------------ 开启和关闭事件调度器…...

Pandas实用Excel数据汇总

Pandas 是一个开源的 Python 库&#xff0c;由 Wes McKinney 开发&#xff0c;专门用于高效地处理和分析数据&#xff0c;无论是小规模的数据实验还是大规模的数据处理任务。它构建在 NumPy 之上&#xff0c;这意味着它利用了 NumPy 的高性能数组计算能力。Pandas 的核心数据结…...

【计算机网络】[第4章 网络层][自用]

1 概述 (1)因特网使用的TCP/IP协议体系(四层)的网际层,提供的是无连接、不可靠的数据报服务; (2)ATM、帧中继、X.25的OSI体系(七层)中的网络层,提供的是面向连接的、可靠的虚电路服务。 (3)路由选择分两种: 一种是由用户or管理员人工进行配置(只适用于规…...

Unity3D Entity_CacheService实现详解

Unity3D是一款广泛使用的游戏开发引擎&#xff0c;它提供了丰富的功能和工具来帮助开发者创建高质量的游戏和互动体验。在Unity开发过程中&#xff0c;资源管理是一个重要的环节&#xff0c;特别是当项目规模逐渐增大&#xff0c;资源数量变多时。为了优化资源的加载和管理&…...

DLMS/COSEM协议—(Green-Book)Gateway protocol

DLMS/COSEM协议 — Gateway protocol 10.10 Gateway protocol &#xff08;网关协议&#xff09;10.10.1 概述10.10.2 网关协议 &#xff08;The gateway protocol&#xff09;10.10.3 HES在WAN/NN中作为发起者&#xff08;拉取操作&#xff09;10.10.4 LAN中的终端设备作为发起…...

Android高级面试_12_项目经验梳理

Android 高级面试-1&#xff1a;Handler 相关 问题&#xff1a;Handler 实现机制&#xff08;很多细节需要关注&#xff1a;如线程如何建立和退出消息循环等等&#xff09; 问题&#xff1a;关于 Handler&#xff0c;在任何地方 new Handler 都是什么线程下? 问题&#xff1a…...

【项目实训】解决前后端跨域问题

由于前端框架使用vue&#xff0c;后端使用flask&#xff0c;因此需要解决前后端通信问题 在vue.config.js中修改 module.exports defineConfig({transpileDependencies: true,lintOnSave:false, }) // 跨域配置 module.exports {devServer: { //记住&#x…...

Java反射API详解与应用场景

一、Java反射API简介: 一、什么是反射: 反射是一种强大的工具,它允许我们在运行时检查类、方法和字段的信息,甚至允许我们动态的调用特定类的方法或改变字段的值。编程语言中的反射机制通常用于从类、对象或方法中检索元数据,或者更特别的说,从代码本身中获取信息。这就…...

【例子】webpack 开发一个可以加载 markdown 文件的加载器 loader 案例

Loader 作为 Webpack 的核心机制&#xff0c;内部的工作原理却非常简单。接下来我们一起来开发一个自己的 Loader&#xff0c;通过这个开发过程再来深入了解 Loader 的工作原理。 这里我的需求是开发一个可以加载 markdown 文件的加载器&#xff0c;以便可以在代码中直接导入 m…...

揭秘!这款电路设计工具让学校师生都爱不释手——SmartEDA的魔力何在?

随着科技的飞速发展&#xff0c;电子设计已成为学校师生们不可或缺的技能之一。而在众多的电路设计工具中&#xff0c;有一款名为SmartEDA的工具&#xff0c;凭借其强大的功能和友好的用户体验&#xff0c;迅速赢得了广大师生的青睐。今天&#xff0c;就让我们一起探索SmartEDA…...

onlyoffice实现打开文档的功能

后端代码 import api from api import middlewareasync def doc_callback(request):data await api.req.get_json(request)print("callback ", data)# status 2 文档准备好被保存# status 6 文档编辑会话关闭return api.resp.success()app api.Api(routes[api.…...

基于 SpringBoot + Vue 的图书购物商城项目

本项目是一个基于 SpringBoot 和 Vue 的图书购物商城系统。系统主要实现了用户注册、登录&#xff0c;图书浏览、查询、加购&#xff0c;购物车管理&#xff0c;订单结算&#xff0c;会员折扣&#xff0c;下单&#xff0c;个人订单管理&#xff0c;书籍及分类管理&#xff0c;用…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...