0

0

如何在Go中编写基准测试_Go Benchmark函数写法

P粉602998670

P粉602998670

发布时间:2026-01-17 17:11:00

|

357人浏览过

|

来源于php中文网

原创

Go基准测试函数必须以Benchmark为前缀、参数为*testing.B且文件名以_test.go结尾;运行命令为go test -bench=.;b.N由框架动态调整以确保总耗时约1秒,不可手动赋值。

如何在go中编写基准测试_go benchmark函数写法

Go基准测试必须用Benchmark前缀函数

Go的go test只识别以Benchmark开头、参数为*testing.B的函数。写成TestXxxbenchXxx都不会被运行。

  • 函数签名必须是func BenchmarkXxx(b *testing.B),大小写和参数类型都不能错
  • 文件名需以_test.go结尾,且与被测代码在同一包下(通常同目录)
  • 运行命令是go test -bench=.,不是go rungo build

b.N不是循环次数,而是框架动态调整的迭代基数

Go基准测试会自动多次运行函数,并根据耗时调整b.N值,目标是让单次执行时间稳定在约1秒左右。你不能手动设b.N = 1000来“控制次数”——这会被忽略,且破坏结果准确性。

  • 所有逻辑必须放在for i := 0; i 循环内,否则计时不包含实际工作
  • 初始化开销(如构建大slice、打开文件)应放在b.ResetTimer()之前,避免计入基准耗时
  • 若需预热(warm-up),可加一次空跑:for i := 0; i ,再调b.ResetTimer()
func BenchmarkMapAccess(b *testing.B) {
    m := make(map[int]int)
    for i := 0; i < 1000; i++ {
        m[i] = i * 2
    }
    b.ResetTimer() // 重置计时器,跳过建map的开销
    for i := 0; i < b.N; i++ {
        _ = m[i%1000] // 实际被测操作
    }
}

避免在基准测试中触发GC或内存分配干扰结果

频繁分配内存会引入GC抖动,导致ns/op波动大、不可比。尤其注意字符串拼接、fmt.Sprintf、切片append未预分配等隐式分配。

Text-To-Song
Text-To-Song

免费的实时语音转换器和调制器

下载
  • b.ReportAllocs()开启内存统计,观察B/opallocs/op
  • 提前分配好切片容量:result := make([]int, 0, b.N),而非make([]int, b.N)(后者可能浪费空间)
  • 避免在循环内调用log.Printfmt.Println——它们分配并写IO,直接让基准失效

对比多个实现时,用子基准测试保持环境一致

不要写多个独立的BenchmarkXxx函数来比性能——它们可能在不同GC周期、不同CPU调度下运行。改用b.Run做子基准,共享同一轮驱动逻辑。

  • 每个b.Run子项单独计时,但复用外层预热和初始化
  • 名字用短标识符(如"map""slice"),避免空格或特殊字符
  • 子基准里仍要遵守b.N循环规则,不能省略
func BenchmarkSearch(b *testing.B) {
    data := make([]int, 1e6)
    for i := range data {
        data[i] = i
    }
    b.Run("map", func(b *testing.B) {
        m := make(map[int]bool)
        for _, x := range data {
            m[x] = true
        }
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
            _ = m[data[i%len(data)]]
        }
    })
    b.Run("slice", func(b *testing.B) {
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
            found := false
            for _, x := range data {
                if x == data[i%len(data)] {
                    found = true
                    break
                }
            }
            _ = found
        }
    })
}

真实压测中,b.N可能从几万跳到几百万,取决于函数快慢;如果发现allocs/op远高于预期,大概率是某处悄悄new了对象——这时候go tool pprof比盯着数字更有用。

相关专题

更多
python中print函数的用法
python中print函数的用法

python中print函数的语法是“print(value1, value2, ..., sep=' ', end=' ', file=sys.stdout, flush=False)”。本专题为大家提供print相关的文章、下载、课程内容,供大家免费下载体验。

184

2023.09.27

mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

180

2023.12.04

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

279

2024.02.23

java标识符合集
java标识符合集

本专题整合了java标识符相关内容,想了解更多详细内容,请阅读下面的文章。

253

2025.06.11

c++标识符介绍
c++标识符介绍

本专题整合了c++标识符相关内容,阅读专题下面的文章了解更多详细内容。

121

2025.08.07

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

257

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

208

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1465

2023.10.24

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

27

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.8万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号