最近,我开始学习Go,我正在尝试实现一个可以被多个组并发使用的映射。我希望能够将我的实现与简单的sync.Mutex-protected映射进行比较,或者类似于这样的东西:map.go
通过使用Google,我假设一种简单的基准测试方法将允许许多不必要的优化破坏实际的结果。使用testing.B的基准测试是否使用了一些技术来避免这种情况(毕竟Go和杯标都是Google项目)?如果是,他们知道吗?如果没有,在Go中进行微基准测试的最佳方法是什么?
发布于 2016-05-02 05:27:46
把我的评论转换成回答。
要做到完全准确,任何基准测试都应该小心避免编译器优化,消除测试中的函数,并人为地降低基准测试的运行时间。
var result int
func BenchmarkFibComplete(b *testing.B) {
var r int
for n := 0; n < b.N; n++ {
// always record the result of Fib to prevent
// the compiler eliminating the function call.
r = Fib(10)
}
// always store the result to a package level variable
// so the compiler cannot eliminate the Benchmark itself.
result = r
}来源
下面的页面也可能很有用。
另一个有趣的读物是
另一个有趣的标志是-N,它将禁用编译器中的优化传递。
Source1 Source2
我不是百分之百肯定,但以下应该禁用优化?有更多经验的人需要证实这一点。
go test -gcflags=-N -bench=.发布于 2016-05-01 14:47:24
在Java中,由于Hotspot编译器的工作方式,很难实现微基准测试。如果您只是一遍又一遍地运行相同的代码,您就会发现它会变得更快,从而抛出您的平均值。为了补偿,卡里珀必须做一些热身运行和其他技巧,试图获得一个稳定的基准。
在Go中,情况是静态编译的。没有像系统一样的运行时热点。它真的不需要做任何技巧来获得一个好的时机。
B功能应该不会影响您的代码的性能,所以您不应该做任何特殊的事情。
发布于 2016-05-01 15:19:10
@David给出了很多很好的信息,我同意Go与Java之间的关系,但是在微基准测试中仍然有很多事情需要考虑。它们中的大多数归结为“这与您的用例匹配得有多近?”例如,不同的并发模式在争用情况下的执行情况非常不同。你认为多个同步作者是常见的吗?一位作家,很多读者?很多读者,罕见的写作?单通道?不同的生产者/消费者访问地图的不同部分?在基准测试中执行出色的方案对于其他用例来说可能是垃圾。
类似地,您可能会发现您的方案是否非常依赖于引用的局部性。如果反复读取相同的值,则有些方法的执行情况非常不同(因为它们停留在CPU上缓存中)。这在微基准测试中非常常见,但可能并不能很好地表示您的预期用例。
这并不是说微基准测试是无用的,只是它们常常几乎无用:D…至少是为了得出一般性的结论。如果您正在为一个特定的项目构建它,只需确保您正在根据符合您的用例的实际数据和模式进行测试(理想情况下,只需将其转换为您的程序的真正基准,而不是数据结构的“微基准”)。如果您正在为一般用途构建该工具,则需要确保您是在针对广泛的用例进行基准测试,然后才能得出太多关于它是否更好的结论。
如果这只是教育,那就太棒了。学习为什么一个特定的计划在不同的情况下更好或更坏是很好的经验。只是不要把你的调查结果推到你的证据之外。
https://stackoverflow.com/questions/36966947
复制相似问题