首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Go语言中常见100问题-#89 Writing inaccurate benchmarks

Go语言中常见100问题-#89 Writing inaccurate benchmarks

作者头像
数据小冰
发布于 2023-08-17 00:35:04
发布于 2023-08-17 00:35:04
31900
代码可运行
举报
文章被收录于专栏:数据小冰数据小冰
运行总次数:0
代码可运行
性能测试benchmark编写不正确

我们不要猜测程序性能,在对代码进行优化的时候,可能会有很多因素发挥作用,所以需要综合考虑,进行测试验证准没错。然而,编写benchmark并不是一件简单的事情,很容易因编写错误的benchmark导致做出不正确优化。本章节将列举一系列非正确编写benchmark问题点。

在讨论问题点之前,简单回顾下Go语言中benchmark测试方法,整个骨架代码如下所示。性能测试函数以Benchmark开头,被测试函数foo放在循环中,一共循环b.N次,在运行时,b.N的值根据性能测试时间来设定,默认情况下,benchmark执行时间为1秒,不过可以通过参数 -benchtime重新设置。b.N值从1开始,如果循环逻辑在1秒能够完成,b.N 的值会按照序列 1,2,5,10,20,50,... 增加,同时再次运行基准测试函数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func BenchmarkFoo(b *testing.B) {
 for i := 0; i < b.N; i++ {
  foo()
 }
}

执行性能测试函数命令如下,在1秒内执行73次foo调用,foo平均执行时间为16511228纳秒。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ go test -bench=.
cpu: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
BenchmarkFoo-4                73          16511228 ns/op

现在可以通过设置 -benchtime为2秒,调整性能测试运行时间。foo被执行150次,近乎是前面的2倍。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ go test -bench=. -benchtime=2s
BenchmarkFoo-4               150          15832169 ns/op
没有重置或暂停timer

有时候,我们需要在benchmark循环开始之前做一些操作,这些操作可能需要花费一定时间(例如,创建一个大的切片数据)并且会影响性能测试结果。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func BenchmarkFoo(b *testing.B) {
 expensiveSetup()
 for i := 0; i < b.N; i++ {
  functionUnderTest()
 }
}

在这种情况下,我们需要在开始循环之前调用 ResetTimer 方法. 调用该方法将已流逝的benchmark时间和内存分配计数器归零,这样可以消除 expensiveSetup对测试结果影响。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func BenchmarkFoo(b *testing.B) {
 expensiveSetup()
 b.ResetTimer()
 for i := 0; i < b.N; i++ {
  functionUnderTest()
 }
}

如果要执行的其它操作需要在循环内部进行呢?这种情况如何处理?这时就不能再调用ResetTimer,每次循环将benchmark时间和内存分配计数器归零。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func BenchmarkFoo(b *testing.B) {
 for i := 0; i < b.N; i++ {
  expensiveSetup()
  functionUnderTest()
 }
}

我们可以在 expensiveSetup执行前停止Timer,在该函数执行完后恢复Time. 代码框架如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func BenchmarkFoo(b *testing.B) {
 for i := 0; i < b.N; i++ {
  b.StopTimer()
  expensiveSetup()
  b.StartTimer()
  functionUnderTest()
 }
}

「NOTE注意一点:如果待测的性能函数相比辅助函数运行更快,则可能会导致整个benchmark时间偏长。因为完成整个测试辅助函数也占用了不少时间,所以运行时间要大于1秒。benchmark时间统计的只是funtionUnderTest执行所用时间,如果在循环中辅助函数运行要花费不少时间,完成整个benchmark测试需要更长时间,这时想要性能测试在较短时间完成,一种可行的方法是将benchtime设置为较小值。」

对小规模基准测试做出错误假设

小规模基准测试测量的是一个较小的执行单元,很容易对其做出错误的假设。下面通过一个例子说明,现在给变量原子赋值,不知道选用 atomic.StoreInt32atomic.StoreInt64哪种方法好(保存的是一个4字节数据),分别对其进行性能测试。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func BenchmarkAtomicStoreInt32(b *testing.B) {
 var v int32
 for i := 0; i < b.N; i++ {
  atomic.StoreInt32(&v, 1)
 }
}

func BenchmarkAtomicStoreInt64(b *testing.B) {
 var v int64
 for i := 0; i < b.N; i++ {
  atomic.StoreInt64(&v, 1)
 }
}

上述benchmark运行结果如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go test -bench=.                                                                                   
cpu: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
BenchmarkAtomicStoreInt32-4     233152768                5.266 ns/op
BenchmarkAtomicStoreInt64-4     228359295                5.145 ns/op

测试结果表明StoreInt64比Store32要快,为了公平起见,交互下两个benchmark位置,即先测试BenchmarkAtomicStoreInt64,然后再测试BenchmarkAtomicStoreInt32。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go test -bench=.                                                                                       
cpu: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
BenchmarkAtomicStoreInt64-4     223825905                5.043 ns/op
BenchmarkAtomicStoreInt32-4     237407841                5.037 ns/op

奇怪了?现在运行的结果是StoreInt32比StoreInt64快。为啥这样呢?在小规模基准测试中,影响结果因素有很多,像在运行基准测试时、电源管理、热缩放时机器活动等。

「NOTE 我们应该确保执行基准测试的机器处于空闲状态,但是有其他进程可能在后台运行,这会影响基准测试结果。可以采用 perflock 工具限制基准测试消耗多少CPU. 例如,可以运行一个基准测试使用总可用CPU的70%,将其他的30%分配给操作系统和其他进程,通过这种方式减少其他因素对性能测试结果影响。」

一种处理方法是增加性能测试时间,通过 -benchtime 选项设置。类似于概率论中大数定律,对性能做很多次测试,测试结果将趋于真实值(假设忽略掉指令缓存以及类似机制影响)。

另一种处理方法是在经典的基准测试工具基础上使用一些其他工具。例如,benchstat工具,它是Golang官方推荐的一款命令行工具,可以针对一组或多组样本进行分析,其源码在 golang.org/x里面。

通过设置 -count 参数 为10, 运行10次性能测试,并将测试结果通过管道输出到文件中。操作命令如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
go test -bench=. -count=10 | tee stats.txt   

cpu: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
BenchmarkAtomicStoreInt64-4     236803782                5.048 ns/op
BenchmarkAtomicStoreInt64-4     237760161                5.061 ns/op
BenchmarkAtomicStoreInt64-4     237598474                5.070 ns/op
BenchmarkAtomicStoreInt64-4     237964878                5.053 ns/op
BenchmarkAtomicStoreInt64-4     237597190                5.068 ns/op
BenchmarkAtomicStoreInt64-4     238228754                5.043 ns/op
BenchmarkAtomicStoreInt64-4     236419087                5.046 ns/op
BenchmarkAtomicStoreInt64-4     237955666                5.064 ns/op
BenchmarkAtomicStoreInt64-4     237543985                5.044 ns/op
BenchmarkAtomicStoreInt64-4     236941857                5.066 ns/op
BenchmarkAtomicStoreInt32-4     237639082                5.060 ns/op
BenchmarkAtomicStoreInt32-4     237918097                5.057 ns/op
BenchmarkAtomicStoreInt32-4     237698049                5.052 ns/op
BenchmarkAtomicStoreInt32-4     236977020                5.043 ns/op
BenchmarkAtomicStoreInt32-4     237817485                5.061 ns/op
BenchmarkAtomicStoreInt32-4     236342242                5.042 ns/op
BenchmarkAtomicStoreInt32-4     236469364                5.049 ns/op
BenchmarkAtomicStoreInt32-4     237664869                5.039 ns/op
BenchmarkAtomicStoreInt32-4     238076143                5.050 ns/op
BenchmarkAtomicStoreInt32-4     237817887                5.042 ns/op
PASS

通过 benchstat工具对输出文件进行性能分析, 如果没有安装 benchstat 通过命令 go install golang.org/x/perf/cmd/benchstat 安装。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
benchstat stats.txt                                                                                   
cpu: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
                   │  stats.txt  │
                   │   sec/op    │
AtomicStoreInt64-4   5.057n ± 0%
AtomicStoreInt32-4   5.050n ± 0%

上述结果表明两者的性能基本是一致的,没有大的差别,Store操作花费的平均时间为5纳秒, 上下浮动在0%,说明结果是挺稳定的。这推翻了前面 atomic.StoreInt32更快或更慢的结论,通过多次测试求平均值,得到真实情况。

通常来说,对小规模基准测试应保持谨慎,在测试时有很多因素会影响结果并误导我们做出错误判断。增加基准测试时间和次数,借助 benchstat 工具有助于得到准确结果。此外,还要注意一点,如果生产环境上的机器与实验测试的机器不一致(CPU类型、位数),线上运行的效果可能与我们预期的不一致。

注意编译器优化

进行基准测试时,要留意编译器优化导致我们做出错误判断。结合golang代码仓库中的14813号问题说明(https://github.com/golang/go/issues/14813), Go语言核心成员 Dave Cheney 也参考该问题讨论。该问题讨论的是一个计数函数,计算一个uint64数二进制中bit为1的数量,实现代码如下。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const m1 = 0x5555555555555555
const m2 = 0x3333333333333333
const m4 = 0x0f0f0f0f0f0f0f0f
const h01 = 0x0101010101010101
 
func popcnt(x uint64) uint64 {
    x -= (x >> 1) & m1
    x = (x & m2) + ((x >> 2) & m2)
    x = (x + (x >> 4)) & m4
    return (x * h01) >> 56
}

编写上面函数的性能测试代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func BenchmarkPopcnt1(b *testing.B) {
 for i := 0; i < b.N; i++ {
  popcnt(uint64(i))
 }
}

进行性能测试得到如下数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cpu: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
BenchmarkPopcnt1-4              1000000000               0.3070 ns/op

平均每次运行时间为0.3070纳秒,太不可思议了,尽然这么短. 0.3070几乎是一个CPU时钟周期,原因在哪里呢?是编译器做了优化处理,上面的被测函数非常简单,被内联处理。内联处理:就是用函数体内容替换函数调用. 一旦函数内联以后,编译器发现处理逻辑对基准测没有任何副作用,直接将其替换为下面的代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func BenchmarkPopcnt1(b *testing.B) {
    for i := 0; i < b.N; i++ {
        // Empty
    }
}

现在benchmark测试代码是空的,也进一步说明了前面性能测试时间几乎是一个CPU时钟周期原因。为了防止编译器进行优化,最佳处理方法如下:

  • 在每次循环中,将运行的结果赋值到一个本地变量中(benchmark函数作用域内)
  • 再将本地变量的值赋值给全局变量

重新编写的性能测试代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var global uint64
 
func BenchmarkPopcnt2(b *testing.B) {
    var v uint64
    for i := 0; i < b.N; i++ {
        v = popcnt(uint64(i))
    }
    global = v
}

「NOTE 为啥不将 popcnt 运行的结果直接赋值给全局变量呢?还要赋值两次,搞这么麻烦!原因是赋值给全局变量的操作比本地变量要慢,在循环内只是赋值给本地变量,在循环外只赋值一次给全局变量减少对性能测试影响。」

运行新版性能测试代码,得到运行结果如下, 可以看到BenchmarkPopcnt2与1有显著不同,它避免了内联优化,版本2是准确的测试结果。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cpu: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
BenchmarkPopcnt1-4              1000000000               0.2815 ns/op
BenchmarkPopcnt2-4              599907250                1.971 ns/op
注意观测者效应

在物理学中,有一个观测者效应,说的是观察行为对被观察系统的干扰影响。对应到本文的性能测试,这种效应也存在,并会导致我们做出错误判断。下面来看一个具体的例子。

需要实现一个函数,该函数入参是一个矩阵,里面的元素是int64类型,矩阵有512列,对矩阵的前8列元素进行求和。

为了优化,我们想知道改变矩阵的列数对结果是否有影响,所以再实现第二版本,接收矩阵有513列。两个版本的函数代码如下。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func calculateSum512(s [][512]int64) int64 {
 var sum int64
 for i := 0; i < len(s); i++ {
  for j := 0; j < 8; j++ {
   sum += s[i][j]
  }
 }
 return sum
}

func calculateSum513(s [][513]int64) int64 {
 var sum int64
 for i := 0; i < len(s); i++ {
  for j := 0; j < 8; j++ {
   sum += s[i][j]
  }
 }
 return sum
}

对上述函数编写性能测试代码,验证上述哪个版本性能更好。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const rows = 1000

var res int64

func createMatrix512(r int) [][512]int64 {
 return make([][512]int64, r)
}

func createMatrix513(r int) [][513]int64 {
 return make([][513]int64, r)
}

func BenchmarkCalculateSum512(b *testing.B) {
 var sum int64
 s := createMatrix512(rows)
 b.ResetTimer()
 for i := 0; i < b.N; i++ {
  sum = calculateSum512(s)
 }
 res = sum
}

func BenchmarkCalculateSum513(b *testing.B) {
 var sum int64
 s := createMatrix513(rows)
 b.ResetTimer()
 for i := 0; i < b.N; i++ {
  sum = calculateSum513(s)
 }
 res = sum
}

嗯,输入的矩阵都是差不多的,一个只是比另一个多1列,但计算的都是前8列,并且两个矩阵的行数都是1000,猜测测试结果是差不多的。实际测试结果是这样的吗?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cpu: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
BenchmarkCalculateSum512-4         97682             12406 ns/op
BenchmarkCalculateSum513-4        151142              7394 ns/op

运行结果与我们想的完全不一致,BenchmarkCalculateSum513 竟然比 BenchmarkCalculateSum512 快50%,为啥是这样的呢?

要搞清楚原因需要知道CPU缓存知识。CPU由不同的缓存组成(L1、L2和L3)。这些高速缓存降低了从主内存访问数据的平均时间成本,在某些情况下,CPU 可以从主存中取出数据并将其复制到 L1, 在这种情况下,CPU 尝试将calculateSum感兴趣的矩阵子集(每行的前八列)存储到 L1 中。但是,矩阵在一种情况下(513 列)适合内存,但在另一种情况下(512 列)不适合内存。

「NOTE 为啥512列的矩阵不适合内存,本文不做分析,将在 #91不了解CPU缓存 中讲解。」

回到本文基准测试,主要问题是在两种情况下都重复使用相同的矩阵。因为函数重复了数千次,所以当函数接收到一个普通的新矩阵时,我们不会测量函数的执行(即将矩阵的创建操作剔除,放到b.ResetTimer前面)。相反,我们测量一个函数,该函数获取一个矩阵,该矩阵已经在缓存中存在单元的子集。因此,由于calculateSum513有更好的缓存命中,它具有更好的执行时间。

这是观察者效应的一个例子。因为我们一直在观察一个重复调用的 CPU密集型 函数,CPU 缓存可能会发挥作用并显着影响结果。在这个例子中,为了防止这种影响,我们应该在每次测试期间创建一个矩阵,而不是重用使用同一个矩阵。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func BenchmarkCalculateSum512_2(b *testing.B) {
 var sum int64
 for i := 0; i < b.N; i++ {
  b.StopTimer()
  s := createMatrix512(rows)
  b.StartTimer()
  sum = calculateSum512(s)
 }
 res = sum
}

func BenchmarkCalculateSum513_2(b *testing.B) {
 var sum int64
 for i := 0; i < b.N; i++ {
  b.StopTimer()
  s := createMatrix512(rows)
  b.StartTimer()
  sum = calculateSum512(s)
 }
 res = sum
}

现在在每次循环迭代期间创建一个新矩阵。如果我们再次运行基准测试(并进行调整benchtime,否则执行时间太长),可以看到两者的运行结果是非常接近的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cpu: Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
BenchmarkCalculateSum512_2-4       41904             31377 ns/op
BenchmarkCalculateSum513_2-4       42580             32396 ns/op

正如本文所见,因为我们重复使用了相同的矩阵,CPU 缓存对结果有很大影响。为了防止这种情况,我们必须在每次循环迭代期间创建一个新矩阵。一般来说,我们应该记住,观察一个被测函数可能会导致结果的显着差异,尤其是在低级优化很重要的CPU密集型函数的微基准测试环境中。在每次迭代期间重新创建数据可能是防止这种影响的好方法。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-08-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据小冰 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
老板:如何证明你的程序性能好?
我们拿处理同一个业务的代码,在同一台机器上运行,相同的次数,就能得出哪个性能更好了。
小锟哥哥
2022/05/10
3010
老板:如何证明你的程序性能好?
Go语言中常见100问题-#94 Not being aware of data alignment
数据对齐是指数据在内存中的分配方式。规则的内存分配可以加速CPU访问内存速度。如果不了解数据对齐,会导致编写的程序消耗额外的内存,并且程序性能低下。
数据小冰
2024/01/10
1600
Go语言中常见100问题-#94 Not being aware of data alignment
Go语言中常见100问题-#95 Not understanding stack vs. heap
在Go语言中,变量可以分配在栈上,也可以分配在堆上。栈内存和堆内存有着本质不同,会对数据密集型应用产生重大影响。本文主要讨论编译器将一个变量分配到栈上还是堆上规则。
数据小冰
2024/01/22
1730
Go语言中常见100问题-#95  Not understanding stack vs. heap
Go语言中常见100问题-#91 Not understanding CPU caches
机械同理心(mechanical sympathy)是三届F1世界冠军杰基·斯图尔特 (Jackie Stewart) 创造的一个术语。
数据小冰
2023/11/29
2790
Go语言中常见100问题-#91 Not understanding CPU caches
100 个 Go 错误以及如何避免:9~12
在前一章中,我们讨论了并发的基础。现在是时候看看 Go 开发人员在使用并发原语时所犯的实际错误了。
ApacheCN_飞龙
2023/10/13
1K0
100 个 Go 错误以及如何避免:9~12
Golang 语言怎么编写测试代码?
我们使用 Golang 语言开发的项目,怎么保证逻辑正确和性能要求呢?也就是说我们如何测试我们的 Golang 代码呢?在 Golang 语言中,可以使用标准库 testing 包编写单元测试和基准测试,使用 go test 命令执行单元测试和基准测试的代码。本文我们介绍在 Golang 语言中怎么编写测试代码。
frank.
2021/10/19
2.2K0
Go语言中常见100问题-#92 Writing concurrent code that leads to false ...
在Go语言中常见100问题-#91 Not understanding CPU caches中讨论了缓存基本概念,可以看到一些特定的缓存(通常是 L1 和 L2)并不在所有逻辑内核之间共享,而是属于一个特定物理内核。这种特殊性会产生一些影响,比如并发时伪共享,这会导致性能显著下降。下面通过一个具体例子来说明什么是伪共享,以及如何预防这种情况发生。
数据小冰
2023/12/13
2110
Go语言中常见100问题-#92 Writing concurrent code that leads to false ...
Go 高性能系列教程之一:基准测试
要想改进程序的性能,首先要知道程序的当前性能。 本节主要关注使用 Go testing 包如何构建有用的基准测试,并且给出一些最佳实践以及常见的陷阱。
Go学堂
2023/01/31
7890
Go语言中常见100问题-#93 Not taking into account instruction-level ...
指令级别并行也是严重影响程序性能的一个原因。在理解什么是指令级并行之前,先来看一个具体的例子,并分析如何优化它。下面的函数接收一个长度为2的int64类型数组,函数内部将迭代一定次数,在每轮迭代时,执行如下操作:
数据小冰
2024/01/02
1630
Go语言中常见100问题-#93 Not taking into account instruction-level ...
Go高性能编程 EP5: 更精准的benchmark
当我们尝试去优化代码的性能时,首先得知道当前的性能怎么样,得到一个基准性能。Go语言标准库内置的 testing 测试框架提供了benchmark的能力。本文主要介绍 如何使用benchmark 进行基准测试,以及如何提高benchmark 的精准度,最后介绍了两个工具,帮助我们更加方便的进行benchmark。
萝卜要努力
2025/03/07
1490
Go高性能编程 EP5: 更精准的benchmark
Go语言中常见100问题-#56 Concurrency isn’t always faster
许多开发人员犯的一个误解是认为并发的处理方法应该总是比顺序的处理方法更快,这是大错特错的。处理方法的整体性能取决于很多因素。例如程序结构的效率(并发性),可以并行处理的部分以及计算单元之间的竞争程度。在本节中,我们将学习一些Go并发的基础知识,并通过一个具体的例子说明并发的处理方法并不是最快的。
数据小冰
2022/08/15
4340
Go语言中常见100问题-#56 Concurrency isn’t always faster
Go语言实战笔记(二十二)| Go 基准测试
基准测试,是一种测试代码性能的方法,比如你有多种不同的方案,都可以解决问题,那么到底是那种方案性能更好呢?这时候基准测试就派上用场了。
飞雪无情
2018/08/28
4160
go benchmark 性能测试
基准测试主要是通过测试CPU和内存的效率问题,来评估被测试代码的性能,进而找到更好的解决方案。
solate
2019/07/22
9.4K0
Go 语言基准测试入门
之前在写 Java 的文章的时候,如果想在本地进行某段代码的性能测试(通常是对比另外一段或者几段),就会用到基准测试框架 JMH ,也的确非常好用。虽然我学习 Go 语言有一段时间了,对于基准测试还没有涉猎,下面就分享Go 语言的基准测试入门实践。
FunTester
2025/01/23
940
Go 语言基准测试入门
Go语言基准测试(benchmark)三部曲之三:提高篇
-《Go语言基准测试(benchmark)三部曲》已近尾声,经历了《基础篇》和《内存篇》的实战演练,相信您已熟练掌握了基准测试的常规操作以及各种参数的用法,现在可以学习一些进阶版的技能了,在面对复杂一些的场景也能高效完成基准测试,另外还有几个坑也要提前了解,避免以后掉进去
程序员欣宸
2023/03/12
4280
Go语言基准测试(benchmark)三部曲之三:提高篇
关于go语言的测试相关内容笔记
其实之前对于测试自己一直比较弱,不管是python的还是go的,关于测试这块并没有非常注重,这次就好好整理一下关于go的测试
coders
2018/11/22
4690
golang性能测试及优化(上)
性能测试Benchmarks的用法和单元测试类似,也是用的testing,性能测试用*testing.B代替*testing.T
机械视角
2019/10/23
7990
go代码测试与调优
Go语言中的测试依赖go test命令。编写测试代码和编写普通的Go代码过程是类似的,并不需要学习新的语法、规则或工具。
PayneWu
2021/04/29
1K0
go代码测试与调优
Go高阶18,go语言测试功能详解-上
您诸位好啊,我是“菜鸟哥”--无尘,最早能看到这篇文章的小伙伴,也应该是中秋假期第一天了,首先祝大家中秋愉快,也感谢大家这么久以来的关注和支持。
微客鸟窝
2021/10/08
4200
Golang基准测试
基准测试常用于代码性能测试,函数需要导入testing包,并定义以Benchmark开头的函数, 参数为testing.B指针类型,在测试函数中循环调用函数多次
仙人技术
2021/08/31
6100
Golang基准测试
相关推荐
老板:如何证明你的程序性能好?
更多 >
LV.0
这个人很懒,什么都没有留下~
目录
  • 性能测试benchmark编写不正确
    • 没有重置或暂停timer
    • 对小规模基准测试做出错误假设
    • 注意编译器优化
    • 注意观测者效应
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档