go - 如何对 init() 函数进行基准测试
问题描述
我正在使用以下 Go 代码,该代码使用查找表计算人口计数:
package population
import (
"fmt"
)
var pc [256]byte
func init(){
for i := range pc {
pc[i] = pc[i/2] + byte(i&1)
}
}
func countPopulation() {
var x uint64 = 65535
populationCount := int(pc[byte(x>>(0*8))] +
pc[byte(x>>(1*8))] +
pc[byte(x>>(2*8))] +
pc[byte(x>>(3*8))] +
pc[byte(x>>(4*8))] +
pc[byte(x>>(5*8))] +
pc[byte(x>>(6*8))] +
pc[byte(x>>(7*8))])
fmt.Printf("Population count: %d\n", populationCount)
}
我编写了以下基准代码来检查上述代码块的性能:
package population
import "testing"
func BenchmarkCountPopulation(b *testing.B) {
for i := 0; i < b.N; i++ {
countPopulation()
}
}
这给了我以下结果:
100000 18760 ns/op
PASS
ok gopl.io/ch2 2.055s
然后我将代码从init()
函数移动到countPopulation()
函数,如下所示:
func countPopulation() {
var pc [256]byte
for i := range pc {
pc[i] = pc[i/2] + byte(i&1)
}
var x uint64 = 65535
populationCount := int(pc[byte(x>>(0*8))] +
pc[byte(x>>(1*8))] +
pc[byte(x>>(2*8))] +
pc[byte(x>>(3*8))] +
pc[byte(x>>(4*8))] +
pc[byte(x>>(5*8))] +
pc[byte(x>>(6*8))] +
pc[byte(x>>(7*8))])
fmt.Printf("Population count: %d\n", populationCount)
}
并再次运行相同的基准代码,这给了我以下结果:
100000 20565 ns/op
PASS
ok gopl.io/ch2 2.303s
观察两个结果后,很明显该init()
函数不在基准函数的范围内。这就是为什么与第二次执行相比,第一次执行基准测试花费的时间更少。
现在我有另一个问题,我正在寻找答案。
如果我只需要对init()
方法进行基准测试,考虑到一个包中可以有多个init()
函数。它是如何完成的golang
?
提前致谢。
解决方案
是init()
的,一个包中可以有多个 ',事实上init()
,一个文件中可以有多个 '。更多关于 init 的信息可以在这里找到。请记住,它init()
会在您的程序启动之前自动调用一次main()
。
基准框架多次运行您的代码(在您的情况下为 100000)。这允许它测量非常短的函数以及非常长的函数。基准包括时间是没有意义的init()
。您遇到的问题是您不了解基准测试的目的。基准测试可让您比较两个或多个单独的实现以确定哪个更快(您也可以根据相同函数的输入比较性能)。它没有告诉你应该在哪里做。
您基本上在做的事情被称为过早优化。这是您开始优化代码的地方,试图使其尽可能快,而不知道您的程序实际上将大部分时间花在了哪里。分析是测量程序的时间和空间复杂度的过程。在实践中,它可以让你看到你的程序大部分时间都花在了哪里。使用这些信息,您可以编写更高效的函数。有关 go 中的分析的更多信息,请参阅此博客文章。