go单元测试之benchmark基准测试详解

目录

与普通测试的区别

举例说明

指令与结果解读

性能比较

并行测试


 

与普通测试的区别

函数参数类型为*testing.B

测试函数名称必须以Benchmark 开头

执行基准测试时,需要添加-bench参数

运行所有基准测试函数

go test –bench=.*

举例说明

编写一个对于for循环的基准测试

func NewStringSlice(n int) []string {rand.Seed(time.Now().UnixNano())arr := make([]string, 0, n)for i := 0; i < n; i++ {arr = append(arr, strconv.Itoa(rand.Int()))}return arr
}func BenchmarkStringSlice100(b *testing.B) {for i := 0; i < b.N; i++ {NewStringSlice(100)}
}func BenchmarkStringSlice1000(b *testing.B) {for i := 0; i < b.N; i++ {NewStringSlice(1000)}
}func BenchmarkStringSlice8000(b *testing.B) {for i := 0; i < b.N; i++ {NewStringSlice(8000)}
}func BenchmarkStringSlice9000(b *testing.B) {for i := 0; i < b.N; i++ {NewStringSlice(9000)}
}func BenchmarkStringSlice10000(b *testing.B) {for i := 0; i < b.N; i++ {NewStringSlice(10000)}
}

运行所有BenchmarkStringSlice开头的基准测试函数:

go test -bench=^BenchmarkStringSlice -benchtime=5s .\testt\ -benchmem

结果如下:

BenchmarkStringSlice100-16                512133             12192 ns/op            4191 B/op        101 allocs/op
BenchmarkStringSlice1000-16               116264             49866 ns/op           40375 B/op       1001 allocs/op
BenchmarkStringSlice8000-16                17469            341199 ns/op          323003 B/op       8001 allocs/op
BenchmarkStringSlice9000-16                15597            383283 ns/op          363379 B/op       9001 allocs/op
BenchmarkStringSlice10000-16               14016            425329 ns/op          403754 B/op      10001 allocs/op
PASS
ok      awesomeProject/testt    43.135s

指令与结果解读

BenchmarkStringSlice100-16结尾的数字16表示GOMAXPROCS的值

-bench=^BenchmarkStringSlice表示所执行的基准测试范围包括以IntSlice结尾的基准测试函数,如果是-bench=abc$则表示所有以abc结尾的基准测试函数

-benchtime=5s表示性能测试运行的时间,默认是1s(1秒是最小值),有时候为了产生更准确的结果,可以增加-benchtime参数,用来指定最小基准时间。

后面的.\testt\表示执行的是testt目录下的测试文件。

-benchmem参数可用来获取执行性能测试时的内存分配数据

【结果】

512133表示发生的调用次数
12192 ns/op表示512133次调用消耗的平均时间为12192纳秒
4191 B/op表示每次操作内存分配了4191字节
101 allocs/op表示每次操作进行的内存分配次数,为101次。

 

性能比较

当算法不同时,我们仅需要以不同的输入来比较不同算法的性能差异,举个例子平时常见的比较有两种:

1、同一个函数,将不同的入参输入,比较不同参数的效果
2、不同的函数,将相同的入参输入,比较各自的效果

显然,做性能比较就是后者,而前者是对一个函数在不同条件下的性能测试。

作者编写了如下三种斐波那契数列的算法实现:

Fibonacci1

func Fibonacci1(num int) int {if num < 1 {return 0}if num == 1 || num == 2 {return 1}return Fibonacci1(num-1) + Fibonacci1(num-2)
}

Fibonacci2

func Fibonacci2(num int) int {if num < 1 {return 0}backMap := make(map[int]int)return fib(backMap, num)
}func fib(backMap map[int]int, num int) int {if num == 1 || num == 2 {return 1}if backMap[num] != 0 {return backMap[num]}backMap[num] = fib(backMap, num-1) + fib(backMap, num-2)return backMap[num]
}

Fibonacci3

func Fibonacci3(num int) int {if num < 1 {return 0}if num == 1 || num == 2 {return 1}left, right, res := 1, 1, 0for i := 3; i <= num; i++ {res = left + rightleft, right = right, res}return res
}

如上都需要一个数值参数,获得一个数值,我们要做的就是计算在相同的入参情况下,三种算法的各自表现。

编写三种算法的基准测试基础函数

func benchmarkFib1(b *testing.B, num int) {for i := 0; i < b.N; i++ {Fibonacci1(num)}
}func benchmarkFib2(b *testing.B, num int) {for i := 0; i < b.N; i++ {Fibonacci2(num)}
}func benchmarkFib3(b *testing.B, num int) {for i := 0; i < b.N; i++ {Fibonacci3(num)}
}

另外编写外层调用,以入参为10举例:

func BenchmarkFib10_1(b *testing.B) { benchmarkFib1(b, 10) }
func BenchmarkFib10_2(b *testing.B) { benchmarkFib2(b, 10) }
func BenchmarkFib10_3(b *testing.B) { benchmarkFib3(b, 10) }

想比较什么值,传不同的值即可。

第一波,验证下入参都为10时的各自效果:

go test -bench=^BenchmarkFib10 -benchtime=10s .\testt\ -benchmemBenchmarkFib10_1-16     94737864               129.1 ns/op             0 B/op          0 allocs/op
BenchmarkFib10_2-16     75052676               163.5 ns/op             0 B/op          0 allocs/op
BenchmarkFib10_3-16     1000000000               1.272 ns/op           0 B/op          0 allocs/op
PASS
ok      awesomeProject/testt    26.942s

就结果而言,算法3明显更优,能支持的执行次数更大,每次调用时间更短,百倍数量级差异。

接着,验证下入参都为50时的各自效果。由于传入数值越大消耗时间就越长,因此为得到更准确的结果,我们将-benchtime调大:

go test -bench=^BenchmarkFib50 -benchtime=50s .\testt\ -benchmemBenchmarkFib50_1-16            1        70255751500 ns/op           2360 B/op          8 allocs/op
BenchmarkFib50_2-16     18577252              9417 ns/op            2401 B/op          9 allocs/op
BenchmarkFib50_3-16     706275607               81.14 ns/op            0 B/op          0 allocs/op
PASS
ok      awesomeProject/testt    369.285s

当入参为50,在相同的时间内(50秒),算法1只被调用了1次,而算法2则是其千万级的数量级优化,算法3更甚。

如果你对第二列被调用了多少次不敏感,或者没什么概念的话,可以这么理解:

执行入参为50的斐波那契数列,在给定的相同时间内,算法1只能执行1次,换句话说它没有机会再执行第二次了;

算法2在相同条件下却可以执行18577252次,消耗160秒;算法3干相同的活在相同条件下可以干706275607次,一共只花了70秒。

并行测试

即以并行的方式执行给定的基准测试。

b.RunParallel 会创建出多个goroutine,并将b.N分配给这些goroutine执行,其中goroutine数量的默认值为GOMAXPROCS。

如果想要增加非CPU受限(non-CPU-bound)基准测试的并行性, 那么可以在RunParallel之前调用 SetParallelism 。举例如下:

func BenchmarkFibParallel10_1(b *testing.B) {b.SetParallelism(2)b.RunParallel(func(pb *testing.PB) {for pb.Next() {Fibonacci1(10)}})
}

执行:

go test -bench=^BenchmarkFibParallel10 -benchtime=10s .\testt\ -benchmem -cpu=1BenchmarkFibParallel10_1        74194387               310.1 ns/op             0 B/op          0 allocs/op
BenchmarkFibParallel10_2        71352631               165.9 ns/op             0 B/op          0 allocs/op
BenchmarkFibParallel10_3        1000000000               1.203 ns/op           0 B/op          0 allocs/op
PASS
ok      awesomeProject/testt    37.271s

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/676857.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

推荐几个Python爬虫接单渠道

前言 平时工作有闲的家人们&#xff0c;今天给大家推荐一些用Python爬虫做私活的渠道&#xff01; 【Python爬虫学习资料】 先给各位还不熟悉Python爬虫的朋友介绍一下&#xff01; 可以短时间获得大量资料~ 可以进一步数据分析 当然也可以获得收益&#xff01; 学会Python…

在 Blazor WASM 中手撸一个.NET MD5类

最近.net8 blazor auto大火, 我也玩了一下,发现ssr能用的代码 MD5 类在wasm是没法用的. 于是搜索了一下互联网,找到了一份代码,分享给大家. 我找到的帖子作者原话: 代码不是我的&#xff0c;但我确实稍微修改了它以使其与 System.Security.Cryptography.MD5 类更加一致。 pub…

第十七篇【传奇开心果系列】Python的OpenCV库技术点案例示例:自适应阈值二值化处理图像提取文字

传奇开心果短博文系列 系列短博文目录Python的OpenCV库技术点案例示例系列短博文目录前言一、自适应阈值二值化处理图像提取文字轮廓的初步示例代码:二、扩展思路介绍三、调整自适应阈值二值化的参数示例代码四、对二值化图像进行形态学操作示例代码五、使用轮廓特征进行筛选示…

113.路径总和 II

给你二叉树的根节点 root 和一个整数目标和 targetSum &#xff0c;找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum 22 输出&a…

【开源】JAVA+Vue+SpringBoot实现实验室耗材管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 耗材档案模块2.2 耗材入库模块2.3 耗材出库模块2.4 耗材申请模块2.5 耗材审核模块 三、系统展示四、核心代码4.1 查询耗材品类4.2 查询资产出库清单4.3 资产出库4.4 查询入库单4.5 资产入库 五、免责说明 一、摘要 1.1…

服务器禁用了请求中指定的方法

服务器禁用了请求中指定的方法 python post请求时报错 服务器禁用了请求中指定的方法 错误代码 response = requests.post(fhttp://api.fe.udream.cc/api/UserEngineering/UpdateTask?usertoken=132e5a6e12a6bbff88154b27b0241819&timestamp={timestamp}, json=json.dumps…

RocketMQ客户端实现多种功能

目录 RocketMQ客户端基本流程 消息确认机制 1、消息生产端采用消息确认加多次重试的机制保证消息正常发送到RocketMQ 单向发送 同步发送 异步发送 2、消息消费者端采用状态确认机制保证消费者一定能正常处理对应的消息 3、消费者也可以自行指定起始消费位点 广播消息 …

技术精英求职必备:测试工程师简历制作全指南

简历编写核心原则 撰写针对软件测试工程师职位的简历时&#xff0c;关键在于精确展现您在软件测试、质量保证和错误诊断方面的专业技能、项目经验和技术成就。简历应作为您展示测试策略设计、自动化测试实施和问题解决能力的窗口&#xff0c;确保每一项经历和技能都与软件测试…

【Web】基于Mybatis的SQL注入漏洞利用点学习笔记

目录 MyBatis传参占位符区别 不能直接用#{}的情况 in多参数值查询 like %%模糊查询 order by列名参数化 MyBatis传参占位符区别 在 MyBatis 中&#xff0c;#{} 和 ${} 都是用于传参的占位符&#xff0c;但它们之间有很大的区别&#xff0c;主要体现在两个方面&#xff1a…

并发容器+并发队列【ConcurentHashMap、CopyOnWriteArrayList、阻塞队列、ArrayBlockingQueue】

并发容器 什么是并发容器?同步容器:并发容器: ConcurrentHashMap结构图JDK1.7结构图JDK1.8结构图 CopyOnWriteArrayList实现原理 并发队列阻塞队列ArrayBlockingQueue 转自极客时间 什么是并发容器? 在JUC包中&#xff0c;有一大部分是关于并发容器的&#xff0c;如Concurr…

【Python中Selenium元素定位的各种方法】

1、元素定位操作&#xff1a; 2、创建浏览器驱动操作&#xff0c;导入By模块&#xff1a; from selenium import webdriver # 用于界面与浏览器互动 from selenium.webdriver.common.by import By # 用于元素定位 driver webdriver.Chrome() # 调用Chrome类&#xff0c;创…

材料非线性Matlab有限元编程:初应力法与初应变法

导读:本文主要围绕材料非线性问题的有限元Matlab编程求解进行介绍,重点围绕牛顿-拉普森法(切线刚度法)、初应力法、初应变法等三种非线性迭代方法的算法原理展开讲解,最后利用Matlab对材料非线性问题有限元迭代求解算法进行实现,展示了实现求解的核心代码。这些内容都将收…

2023年总结

人们总说时间会改变一切&#xff0c;但事实上你得自己来。 今年开始给自己的时间读书、工作、生活都加上一个2.0的release版本号&#xff0c;相比过去的一年还是有很多进步的。 就跟git commit一样&#xff0c;一步一步提交优化&#xff0c;年底了发个版本。用李笑来的话说&am…

【洛谷题解】P1595 信封问题

题目链接&#xff1a;信封问题 - 洛谷 题目难度&#xff1a;普及- 涉及知识点&#xff1a;错排 题意&#xff1a; 分析&#xff1a;直接用错排公式代入即可 AC代码推理公式&#xff1a; #include<bits/stdc.h> using namespace std; long long f[25]; int main()//用…

服务器被黑,安装Linux RootKit木马

前言 疫情还没有结束&#xff0c;放假只能猫家里继续分析和研究最新的攻击技术和样本了&#xff0c;正好前段时间群里有人说服务器被黑&#xff0c;然后扔了个样本在群里&#xff0c;今天咱就拿这个样本开刀&#xff0c;给大家研究一下这个样本究竟是个啥&#xff0c;顺便也给…

《MySQL 简易速速上手小册》第10章:未来趋势和进阶资源(2024 最新版)

文章目录 10.1 MySQL 在云计算和容器化中的应用10.1.1 基础知识10.1.2 重点案例&#xff1a;使用 Python 部署 MySQL 到 Kubernetes10.1.3 拓展案例 1&#xff1a;在 AWS RDS 上部署 MySQL 实例10.1.4 拓展案例 2&#xff1a;使用 Docker 部署 MySQL 10.2 MySQL 和 NoSQL 的整合…

基于图像掩膜和深度学习的花生豆分拣(附源码)

目录 项目介绍 图像分类网络构建 处理花生豆图片完成预测 项目介绍 这是一个使用图像掩膜技术和深度学习技术实现的一个花生豆分拣系统 我们有大量的花生豆图片&#xff0c;并以及打好了标签&#xff0c;可以看一下目录结构和几张具体的图片 同时我们也有几张大的图片&…

基于片段的3D分子生成扩散模型 - AutoFragDiff 评测

AutoFragDiff 是一个基于片段的&#xff0c;自回归的&#xff0c;口袋条件下的&#xff0c;3D分子生成扩散模型。 AutoFragDiff方法来源于文章《Autoregressive fragment-based diffusion for pocket-aware ligand design》&#xff0c;由加州大学的Mahdi Ghorbani等人于2023年…

星辰AI大模型TeleChat-7B评测

0x0. 前言 受中电信 AI 科技有限公司的邀请&#xff0c;为他们近期开源的TeleChat-7B大模型做一个评测。 TeleChat-7B是由中电信 AI 科技有限公司发的第一个千亿级别大模型&#xff0c;基于transformer decoder架构和清洗后的1TB高质量数据训练而成&#xff0c;取得了相同参数…

【Java EE初阶十一】文件操作(IO)

1. 认识文件 所谓的文件是一个广义的概念&#xff0c;可以代表很多东西&#xff1b;在操作系统里面&#xff0c;会把很多的硬件设备和软件设备都抽象成“文件”&#xff0c;统一进行管理&#xff1b;但是大部分情况下&#xff0c;我们读到的文件&#xff0c;都是指硬盘的文件&a…