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

Go怎么做性能优化工具篇之基准测试

一、什么是基准测试(Benchmark)

在 Go 中,基准测试是通过创建以 Benchmark 开头的函数,并接收一个 *testing.B 类型的参数来实现的。testing.B 提供了控制基准测试执行的接口,比如设置测试执行的次数、记录每次执行的时间等。

每个基准测试函数都必须接受一个 *testing.B 类型的参数。函数体内通过 b.N来控制基准测试的执行次数,Go 会自动调整 b.N 的值,确保每次基准测试运行的时间足够长。

例如:

package main

import (
	"testing"
)

// 基准测试函数
func BenchmarkMyFunction(b *testing.B) {
	// 这里是测试的代码,每次循环 b.N 次
	for i := 0; i < b.N; i++ {
		// 被测试的函数或代码块
		_ = "hello"
	}
}

二、怎么进行基准测试

要运行基准测试,可以使用 go test 命令,指定 -bench 标志来启动基准测试。

go test -bench .
  • bench .:表示运行当前目录下所有以 Benchmark 开头的函数。
  • bench <pattern> :可以通过提供正则表达式来运行特定的基准测试,比如 go test -bench BenchmarkMyFunction 仅运行 BenchmarkMyFunction。

运行基准测试并报告内存分配

go test -bench . -benchmem
  • benchmem:该标志会显示内存分配的详细信息,包括每次基准测试中分配了多少内存。
package main

import (
	"testing"
	"unsafe"
)

func BenchmarkBytes2Str(b *testing.B) {
	aa := []byte("mclink")
	for n := 0; n < b.N; n++ {
		Bytes2Str(aa)
	}
}
func BenchmarkBytes2StrUnsafe(b *testing.B) {
	aa := []byte("mclink")
	for n := 0; n < b.N; n++ {
		Bytes2StrUnsafe(aa)
	}
}

func Bytes2Str(b []byte) string {
	return string(b)
}

func Bytes2StrUnsafe(b []byte) string {
	return *(*string)(unsafe.Pointer(&b))
}

在这里插入图片描述
#从左到右分别表示benchmark函数、运行次数、单次运行消耗的时间、单次运行内存分配的字节数和次数

BenchmarkBytes2Str-8 :基准测试的名称和 CPU 核心数量(这里 -8 表示在 8 核 CPU 上运行)。
317858601:测试函数执行了 20,000,000 次。
3.720 ns/op:每次执行 BenchmarkBytes2Str-8 的平均耗时为 3.72 纳秒。
0 B/op:每次测试没有内存分配。
0 allocs/op:每次测试没有进行内存分配。

三、复杂的基准测试

有时在基准测试中,某些初始化工作并不应该计入测试时间。可以使用 b.StartTimer() 和 b.StopTimer() 来控制计时开始和结束。

func BenchmarkWithStartStopTimer(b *testing.B) {
	// 1. 先进行一些初始化工作
	setup()

	// 2. 在基准测试前停止计时(这部分不会计入基准测试时间)
	b.StopTimer()

	// 3. 进行某些准备工作或其他代码,这部分不会计入基准测试时间
	time.Sleep(100 * time.Millisecond)

	// 4. 启动计时,开始计入基准测试时间
	b.StartTimer()

	// 5. 开始基准测试
	for i := 0; i < b.N; i++ {
		performWork()
	}

	// 6. 结束时停止计时
	b.StopTimer()
}

  • b.StartTimer():开始计时。
  • b.StopTimer():停止计时。
  • b.ResetTimer():重置计时器,确保计时仅限于你关心的代码

你可以使用 b.ReportAllocs() 启用内存报告,来查看每次基准测试中分配了多少内存。

func BenchmarkAllocations(b *testing.B) {
    b.ReportAllocs() // 启用内存分配报告
    for i := 0; i < b.N; i++ {
        _ = make([]byte, 1024) // 模拟内存分配
    }
}

在这里插入图片描述

  • 通过 -benchtime 设置基准测试时间
    go test 命令支持 -benchtime 标志,可以控制基准测试的执行时长。例如,如果你想要让基准测试执行 2 秒钟:
go test -bench . -benchtime=2s
  • 跳过普通单元测试,只运行基准测试
    如果你只想运行基准测试,而跳过普通的单元测试,可以使用 -run=^$ 来过滤单元测试:
go test -bench . -run=^$
  • 和pprof 混合双打
package main

import (
	"fmt"
	"testing"
	"time"
	"runtime/pprof"
	"os"
)

// 需要进行基准测试的函数
func performTask() {
	// 模拟耗时操作
	time.Sleep(100 * time.Millisecond)
}

// 基准测试函数
func BenchmarkWithPprof(b *testing.B) {
	// 创建一个文件来保存 CPU 分析数据
	f, err := os.Create("cpu.pprof")
	if err != nil {
		b.Fatal("could not create CPU profile: ", err)
	}
	defer f.Close()

	// 启动 pprof,开始记录 CPU 使用情况
	if err := pprof.StartCPUProfile(f); err != nil {
		b.Fatal("could not start CPU profile: ", err)
	}
	defer pprof.StopCPUProfile()

	// 进行基准测试
	for i := 0; i < b.N; i++ {
		performTask()
	}
}

// 运行基准测试的命令:go test -bench .
// 运行完之后会生成一个 cpu.pprof 文件,可以用 go tool pprof 查看分析数据。

如何使用 pprof 请看上一篇文章。

下一篇:Go的 Trace 工具~


http://www.kler.cn/a/449375.html

相关文章:

  • jsp中的四个域对象(Spring MVC)
  • 什么是MVCC?
  • 蓝桥杯物联网开发板硬件组成
  • 前端使用 Konva 实现可视化设计器(20)- 性能优化、UI 美化
  • 文件操作(File类)
  • Qt之QML应用程序开发:给应用程序添加图标文件
  • 芝法酱学习笔记(2.2)——sql性能优化2
  • 0.96寸OLED显示屏详解
  • Day1 苍穹外卖前端 Vue基础、Vue基本使用方式、Vue-router、Vuex、TypeScript
  • Python实现将series系列数据格式批量转换为Excel
  • OCR(五)linux 环境 基于c++的 paddle ocr 编译【CPU版本 】
  • 高原地区无人机巡检作业技术详解
  • 螺栓连接|结构强度与刚度评定
  • C++练习题之计算天数
  • SpringBoot3-第二篇(Web开发)
  • 使用FreeNAS软件部署ISCSI的SAN架构存储(IP-SAN)练习题
  • 物联网水文观测设备
  • 蓝桥杯物联网开发板硬件组成
  • 汽车IVI中控开发入门及进阶(41):视频播放器MPlayer
  • 单片机的内存是指RAM还是ROM
  • Android Studio Gradle Sync timeout
  • H5海康WS在线视频播放器:打造高效流畅的Web视频体验
  • BufferedWriter(废稿)
  • JUC并发编程之Thread学习笔记
  • count(1)、count(_)与count(列名)的区别?
  • 七牛云短信服务