Go 语言性能测试 - 入门篇

2023-10-27

Go 语言性能测试 - 入门篇

Go 语言是非常高效的,在处理并发请求时的性能表现非常出色,在某些考虑性能因素的场景下,我们需要进行性能测试,Go语言提供了用于性能测试的 testing.B 框架,本篇就介绍下Go语言的性能测试的基本做法。

参考阅读

基本格式

Go 性能测试的函数基本格式:

func BenchmarkXxx(*testing.B)

Benchmark测试通过 go test 命令来启动,通过 -bench 这样一个标签来标明是Benchmark测试,启动后会按照顺序执行。

下面我们有一个简单的例子,这里只有一个输出hello的方法:

benchmark.go

func Hello() {
	fmt.Sprintf("hello")
}

按照规范,我们需要一个benchmark_test.go的文件来测试。

benchmark_test.go

func BenchmarkHello(b *testing.B) {
	for i := 0; i < b.N; i++ {
		Hello()
	}
}

这里的b.N是必须运行的次数,在benchmark运行期间,这个数值会调整,直到可以稳定地评估出性能。

$ go test -bench BenchmarkHello
goos: darwin
goarch: amd64
pkg: demo/benchmark
BenchmarkHello-4   	20000000	        59.4 ns/op
PASS
ok  	demo/benchmark	1.264s

结果表示以 59.4 ns/op 的速度运行了 20000000 次,耗时 1.264 秒

有些时候,我们想多跑几组,对比下性能测试结果是否稳定,我们可以加一些参数:

$ go test -test.bench=BenchmarkHello -count=5
goos: darwin
goarch: amd64
pkg: demo/benchmark
BenchmarkHello-4   	20000000	        59.5 ns/op
BenchmarkHello-4   	20000000	        58.4 ns/op
BenchmarkHello-4   	20000000	        59.7 ns/op
BenchmarkHello-4   	20000000	        58.7 ns/op
BenchmarkHello-4   	20000000	        59.0 ns/op
PASS
ok  	demo/benchmark	6.239s

这里我们跑了五组测试,性能还是相对比较稳定,实际有很多参数是可以加的,整理如下:

-test.bench patten: 只跑那些性能测试用例

-test.benchmem : 是否在性能测试的时候输出内存情况

-test.benchtime t : 性能测试运行的时间,默认是1s

-test.cpuprofile cpu.out : 是否输出cpu性能分析文件

-test.memprofile mem.out : 是否输出内存性能分析文件

-test.parallel n : 性能测试的程序并行cpu数,默认等于GOMAXPROCS。

-test.timeout t : 如果测试用例运行时间超过t,则抛出panic

-test.cpu 1,2,4 : 程序运行在哪些CPU上面,使用二进制的1所在位代表。

-test.short : 将那些运行时间较长的测试用例运行时间缩短

指定cpu运行的时候,我们需要注意的是,比如设置4并不是指在第四个CPU上运行,根据二进制0100可知,是在第三个CPU上运行。这个和nginx的worker_cpu_affinity配置相似。具体请参考:worker_cpu_affinity

并行测试

在某些时候,我们想并行地运行测试用例,我们可以用 b.RunParallel 方法来启动,这时候最好启用 -cpu 参数

func BenchmarkTemplateParallel(b *testing.B) {
	templ := template.Must(template.New("test").Parse("Hello, {{.}}!"))
	b.RunParallel(func(pb *testing.PB) {
		var buf bytes.Buffer
		for pb.Next() {
			buf.Reset()
			templ.Execute(&buf, "World")
		}
	})
}

运行测试用例输出:

$ go test -test.bench=BenchmarkTemplateParallel -cpu 1,2,4
goos: darwin
goarch: amd64
pkg: demo/benchmark
BenchmarkTemplateParallel     	 1000000	      1247 ns/op
BenchmarkTemplateParallel-2   	 2000000	       626 ns/op
BenchmarkTemplateParallel-4   	 2000000	       615 ns/op
PASS
ok  	demo/benchmark	5.035s

我们制定指定在1,2,3号CPU上并行运行,输出结果显示了在三个CPU上运行的速度情况。

我们考虑写如下的测试代码:

func TestFoo(t *testing.T) {
	t.Run("A=1", func(t *testing.T) { fmt.Println("A=1") })
	t.Run("A=2", func(t *testing.T) { fmt.Println("A=2") })
	t.Run("B=1", func(t *testing.T) { fmt.Println("B=1") })
}

这里我们有三个用例,逐一运行,但是重复代码比较多,在上篇Go 语言单元测试(顶部有链接)中提到,最好使用 Table Driven 的形式,那我们来改造下:

func TestGroupedParallel(t *testing.T) {
	tests := []struct {
		Name string
	}{
		{
			Name: "A=1",
		},
		{
			Name: "A=2",
		},
		{
			Name: "B=1",
		},
	}
	for _, tc := range tests {
		tc := tc // capture range variable
		t.Run(tc.Name, func(t *testing.T) {
			t.Parallel()
		})
	}
}

我们通过执行看结果:

$ go test -run TestGroupedParallel -v
=== RUN   TestGroupedParallel
=== RUN   TestGroupedParallel/A=1
=== PAUSE TestGroupedParallel/A=1
=== RUN   TestGroupedParallel/A=2
=== PAUSE TestGroupedParallel/A=2
=== RUN   TestGroupedParallel/B=1
=== PAUSE TestGroupedParallel/B=1
=== CONT  TestGroupedParallel/A=1
=== CONT  TestGroupedParallel/B=1
=== CONT  TestGroupedParallel/A=2
--- PASS: TestGroupedParallel (0.00s)
    --- PASS: TestGroupedParallel/A=1 (0.00s)
    --- PASS: TestGroupedParallel/B=1 (0.00s)
    --- PASS: TestGroupedParallel/A=2 (0.00s)
PASS
ok  	demo/benchmark	0.006s

我们看到三个用例都被执行,代码看起来更优雅。

最后,我们介绍下可以嵌套并行地执行测试用例,如下:

func TestTeardownParallel(t *testing.T) {
    // This Run will not return until the parallel tests finish.
    // <setup code here>
    t.Run("group", func(t *testing.T) {
        t.Run("Test1", parallelTest1)
        t.Run("Test2", parallelTest2)
        t.Run("Test3", parallelTest3)
    })
    // <tear-down code>
}

总结

Go 语言的性能测试其实是一个比较复杂的过程,要结合很多参数,比如 -cpu-membench 等等来深入分析性能细节,这里我们可以考虑采用这些辅助工具来实现,这篇只是一个开始,希望对大家有帮助。

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

Go 语言性能测试 - 入门篇 的相关文章

  • Gitlab CI/CD 在管道之间传递工件/变量

    tl dr 我如何传递数据 例如这 BUILD VERSION变量 Gitlab CI 中不同管道中的作业之间 所以 就我而言 Pipeline 1 on push ect Pipeline 2 after merge building j
  • 如何计算 docker 限制

    我创建了我的码头工人 Python Flask 如何计算内存和 CPU 的限制 我们是否有一些工具可以在具有不同限制的 docker 上运行性能测试 然后建议设置的最佳限制数字是多少 对于已经在容器内运行的应用程序 您可以使用docker
  • 在声明式 Jenkins 管道中的环境变量中存储值列表

    我有以下管道 但我不知道为什么它在第一行代码上失败 pipeline agent any environment def mypods stages stage Getting pods steps script withKubeConfi
  • 如何解决现有文件和符号链接之间的 npm install 冲突?

    我遇到了一个问题NPM https www npmjs com 它似乎正在检测具有相同名称的现有文件和符号链接之间的冲突 运行时我没有看到任何符号链接ls l从我的项目的根文件夹 我如何弄清楚 NPM 发生了什么并解决这个冲突 持续集成构建
  • [每周一更]-(第55期):Go的interface

    参考地址 https juejin cn post 6978322067775029261 https gobyexample com interfaces https go dev tour methods 9 介绍下Go的interfa
  • 2024年度 ROTS - 实时操作系统 Top 15

    RTOS 实时操作系统 这里说的 RTOS 并非新星球大战电影中的机器人 而是物联网设备 航空系统 空中交通管制等背后的无声协调者 就在地球上 RTOS 或称实时操作系统 设计它们是为了更好的管理资源 以及为一些对时间点有精确要求的应用运行
  • Go、Docker、云原生学习笔记全攻略:从零开始,一步步走向精通!(2024版)

    第一章 Go语言学习宝典 一 介绍 01 Go 语言的前生今世 二 开发环境搭建 01 Go 语言开发环境搭建 三 初识GO语言 01 Go 多版本管理工具 02 第一个 Go 程序 hello world 与 main 函数 03 Go
  • 【go语言】读取toml文件

    一 简介 TOML 全称为Tom s Obvious Minimal Language 是一种易读的配置文件格式 旨在成为一个极简的数据序列化语言 TOML的设计原则之一是保持简洁性 易读性 同时提供足够的灵活性以满足各种应用场景 TOML
  • 为本地开发创建不同的 eslint 规则

    这是一个激励人心的例子 我正在开发一些代码并想找出出了什么问题 所以我有 function foo console log Look its 2016 and I m still printf debugging 除了 我们的构建过程将 e
  • f1-micro 中的 GCLOUD Kubernetes 结果为(由于内存不足,不支持 f1-micro 机器的节点池)

    我尝试使用 Google 的 UI 在集群中启动一个新的 f1 micro 节点 但它默默地失败了 所以我决定使用 gcloud 运行它 看看是否提供了更多详细信息 所以我运行了以下命令 gcloud container node pool
  • 什么是 gitlab runner

    我想我从根本上错过了一些东西 我是 CI CD 新手 正在尝试使用 gitlab 建立我的第一个管道 该项目是一个预先存在的 PHP 项目 我还不想清理它 目前我已经将整个东西推入了 docker 容器 并且它与谷歌云的 mysql 数据库
  • 无法终止容器::尝试终止容器,但未收到退出事件

    我无法停止 删除或终止我的 docker 容器 下面给出的命令及其各自的错误消息 1 docker stop
  • 如何在前端js应用程序(如后端应用程序)中使用变量替换?

    我正在尝试为一些应该非常简单的事情找到一个优雅的解决方案 我正在使用 create react app 开发一个 React 应用程序 并且在将代码部署到不同环境 例如在 Azure 中 时 我试图找到一种简单的方法来替换变量 例如 API
  • 将 APK 发布到 Play 商店时出现构建版本问题

    我看过很多答案 但大多数都已经过时了 我正在尝试使用 Azure DevOps 管道将我的 Android 应用程序发布到 Play 商店 我遇到了 APK 版本代码的问题 出现以下错误 APK指定已使用的版本代码 任何人都知道如何增加存在
  • 如何使用jenkins管道将war部署到tomcat?

    我想使用管道部署 war 文件 正确的做法是什么 有没有办法在管道代码中使用部署到容器 调用catalina sh或使用curl命令使用jenkins管理器进行部署的问题是我找不到任何方法来检测成功的部署 有没有标准的方法可以做到这一点 在
  • 使用 TFS 命令行部署 SSIS 项目

    如何从 TFS 2015 部署 SSIS 项目 对于常规数据库项目来说 sqlpackage exe publish与发布配置文件 将 SSIS 项目模型自动部署到服务器中的命令行参数是什么 我们使用的是 SQL Server 2016 E
  • 将容器推送到 Azure 容器注册表时资源访问被拒绝

    使用 Docker Compose 将容器推送到私有 Azure 容器注册表时 Azure DevOps 管道返回以下错误 正在推送 容器 注册表 应用程序 最新 推送引用存储库 docker io registry container 被
  • 如何从 docker 容器运行 webpack 构建?

    我正在制作的应用程序是用 ES6 编写的 其他好东西是由 Docker 容器内的 webpack 转译的 目前 一切工作从创建内部目录 安装依赖项到创建编译的捆绑文件 当运行容器时 它说 dist bundle js 不存在 除非我在主机目
  • 如何对私有 jelastic 环境进行版本控制

    为了跟踪 Jelastic 托管环境的配置 我想在 git 存储库中对其进行版本控制 该存储库应该是私有的 并包含多个具有不同版本的不同分支 例如master abc123 v1 1 我的第一次尝试是创建一个私有 github 存储库 其中
  • 如何在 Jenkins 控制台输出中隐藏 checkout scm 步骤输出

    我在 Jenkinsfile 脚本化管道 中的第一个阶段是 checkout scm 它简要描述了 GitHub checkouts 和所有修订相关的内容我不想在 Jenkins 控制台输出中显示 是否可以将其隐藏在 Jenkins 的控制

随机推荐

  • html的marquee标签,marquee 标签参数详细说明

    marquee 元素 可以 用来插入一段滚动的文字 实现类似走马灯的动效 但这个标签已经过时 MDN文档已经不建议使用 此前因之前项目紧急用过 做个标签参数小结 1 marquee的属性 behavior 设置文本如何滚动 属性值有3种 s
  • React生命周期

    React的生命周期 1 挂载卸载过程 constructor componentWillMount componentDidMount componentWillUnmount 2 更新过程 componentWillReceivePro
  • 利用云服务器搭建解锁网易云变灰歌曲的代理

    前言 最近又在GitHub上发现一个有趣的项目 UnblockNeteaseMusic 还是那句话建议在使用前仔细阅读一下项目的readme 于是打算做一个搭建的教程 本文用搭建了宝塔面板的CentOS的服务器做演示 所以文中包含了宝塔面板
  • C语言常量、变量、标识符

    一 变量概述 变量是一个保存数据的地方 当我们需要在程序里保存数据时 就需要一个变量来保存它 变量定义的一般形式就是 lt 类型名称 gt lt 变量名称 gt 例如 int price int amount int price amoun
  • package.json文件中,^和~的区别

    package json文件里面 显示的是项目所依赖的插件和库的名称和版本 和 就是说明版本号的 它将当前库的版本更新到第一个数字 major version 中的最新版本 比如 12 2 2 库会匹配更新到12 X X的最新版本 但是不会
  • 每日一题 AcWing 99.激光炸弹

    题目 地图上有 N 个目标 用整数 Xi Yi 表示目标在地图上的位置 每个目标都有一个价值 Wi 注意 不同目标可能在同一位置 现在有一种新型的激光炸弹 可以摧毁一个包含 R R 个位置的正方形内的所有目标 激光炸弹的投放是通过卫星定位的
  • 用matplotlib画圆和圆环

    usr bin env python coding UTF 8 import numpy as np from pylab import 创建一个 8 8 点 point 的图 并设置分辨率为 80 figure figsize 8 8 d
  • vsan加入不同型号服务器,VMware VSAN的特点与要求,与优缺点

    VSAN的特点与要求 与优缺点 VMware VSAN主要有5个特点 1 运行在标准x86服务器上 2 分布式集群 把VM数据文件打散放在多个主机上 每个服务器的本地存储网络池化3 使用SSD作为读写缓存加速层 混合型策略 由SSD提供性能
  • 剑指offer_第6题_旋转数组的最小数字

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾 我们称之为数组的旋转 输入一个非减排序的数组的一个旋转 输出旋转数组的最小元素 例如数组 3 4 5 1 2 为 1 2 3 4 5 的一个旋转 该数组的最小值为1 给出的所有元素都大于
  • 机器学习笔记七:使用主成分分析(PCA)对数据集进行降维

    一 前言 有时候我们遇到的一些数据会有很多的特征 几十个 甚至成千上百个 由于此时特征较多 就大大增加了计算的复杂度 鉴于并非所有的特征都非常重要 也为了减少计算的复杂度 我们有必要对数据进行降维 以iris数据集为例 我们都知道 iris
  • python绘制折线图

    俗话说 字不如表 表不如图 图表在数据分析中的作用不言而喻 python中有pandas和matplotlib两个库供使用者来绘制图表 下面来绘制 成绩表 xlsx 的折线图 废话不多说 直接上代码 import pandas as pd
  • 入坑c计划 day3 基本框架的介绍&&输入语法

    我giao 兄弟蒙 我来更新了doge 为了弥补我托更 咱今天加班更新一下新手题型 加油 今天 我们来介绍我们上一节提到的 基本框架 首先 我们先和这个朋友再见个面 怕你们忘记他长什么样子 include
  • 用python制作水仙花

    注 input 输入函数的括号中不允许添加任何信息 提示信息 水仙花数 是指一个三位正整数 其各位数字立方的和等于该数本身 例如 153是一个 水仙花数 因为1 5 3等于153 编程实现 给定一个正整数N 判断100到N之间有多少个 水仙
  • Java---正则

    一 正则表达式常用语法 语法 说明 表示转义字符 匹配输入字符串的开始 匹配输入字符串的结尾 0次或多次匹配前面的字符或表达式 1次或多次匹配前面的字符或表达式 0次或1次匹配前面的字符或表达式 n n为非负整数 固定匹配n次 n n为非负
  • 刷脸支付开启巨额补贴活动扶持力度非常大

    人脸识别设备指纹识别系统需要区别带识别的指纹是来自于人的手指还是指纹手套 人脸识别系统所采集到的人脸图像 是来自于真实的人脸还是含有人脸的照片 因此实际的人脸识别系统一般需要增加活体鉴别环节 例如 要求人左右转头 眨眼睛 开开口说句话等 这
  • jenkins发版工具管理

    从零开始部署一台新的服务器 需要以下几个步骤 1 新增服务器凭据 2 新增服务器连接 3 创建item项目并配置 4 测试发版是否完成 1 新增服务器凭据配置 进入链接 http jenkins地址 credentials store sy
  • 线程的阻塞

    相信像我一样的初学者遇到线程阻塞时会感到无助 那我就把自己对于线程阻塞的理解记录下来吧 线程阻塞时的特点 该线程放弃CPU的使用权 暂停运行 只有当阻塞的原因消除后才回到就绪状态进行运行 被其他的线程中断 该线程也会推出阻塞状态 同时抛出I
  • stable diffusion实践操作-提示词插件安装与使用

    本文专门开一节写提示词相关的内容 在看之前 可以同步关注 stable diffusion实践操作 正文 1 提示词插件安装 1 1 安装 1 2 加载 应用更改并重载前端 1 3 界面展示 点击下面红框按钮 可以出现提示词列表 1 4 使
  • Latex中点乘、希腊字母、花写字体等

    Latex中点乘 希腊字母等 Latex中点乘 希腊字母等 Latex中的乘法 希腊字母表 花写字体 Latex中点乘 希腊字母等 使用Latex进行公式编辑时 由于某些符号不经常用到 老是忘记 所以谢一篇文章来总结 记录一下 Latex中
  • Go 语言性能测试 - 入门篇

    Go 语言性能测试 入门篇 Go 语言是非常高效的 在处理并发请求时的性能表现非常出色 在某些考虑性能因素的场景下 我们需要进行性能测试 Go语言提供了用于性能测试的 testing B 框架 本篇就介绍下Go语言的性能测试的基本做法 参考