Go testing.B 基准测试是否可以防止不必要的优化?

Do Go testing.B benchmarks prevent unwanted optimizations?

我最近开始学习 Go,我正在尝试实现一个可以由多个 groutines 同时使用的映射。我希望能够将我的实现与简单的 sync.Mutex-protected 地图或类似这样的东西进行比较:https://github.com/streamrail/concurrent-map/blob/master/concurrent_map.go

从使用 Google Caliper 开始,我假设一种天真的基准测试方法会允许许多不需要的优化破坏实际结果。使用 testing.B 的基准是否采用了一些技术来避免这种情况(毕竟 Go 和 Caliper 都是 Google 项目)?如果是,他们知道吗?如果不是,在 Go 中进行微基准测试的最佳方法是什么?

在 Java 中,由于 Hotspot 编译器的工作方式,微基准测试更难进行。如果您只是简单地 运行 一遍又一遍地使用相同的代码,您通常会发现它变得更快,这会偏离您的平均水平。作为补偿,Caliper 必须做一些预热 运行s 和其他技巧来尝试获得稳定的基准。

在 Go 中,事物是静态编译的。没有 运行time Hotspot 之类的系统。它真的不需要做任何技巧来获得一个好的时机。

testing.B 功能应该不会影响代码的性能,因此您不必做任何特殊的事情。

@David Budworth 提供了很多有用的信息,我同意 Go vs Java,但是在微基准测试中您仍然需要考虑很多事情。他们中的大多数归结为 "how closely does this match your use case?" 例如,不同的并发模式在争用下表现非常不同。您是否期望多个同时编写器很常见?一个作家,许多读者?读者多,文案难得?单次访问?不同 producers/consumers 访问地图的不同部分?在您的基准测试中表现出色的方案对于其他用例可能是垃圾。

同样,您可能会发现您的方案是否非常依赖于参考位置。如果一遍又一遍地读取相同的值(因为它们保留在 on-CPU 缓存中),一些方法的表现会非常不同。这在微基准测试中很常见,但可能不能很好地说明您的预期用例。

这并不是说微基准测试没有用,只是说它们经常 几乎 没用 :D ......至少对于得出一般结论而言。如果您正在为特定项目构建它,只需确保您正在针对与您的用例相匹配的真实数据和模式进行测试(理想情况下,只需将其变成您程序的真实基准,而不是 "microbenchmark" 的数据结构)。如果您正在为一般用途构建它,则需要确保在对它是否更好做出太多结论之前,您针对广泛的用例进行了基准测试。

如果它只是教育性的,那就太棒了。了解为什么特定方案在不同情况下效果更好或更差是很好的体验。只是不要将你的发现强加于你的证据。

正在将我的评论转换为答案。

To be completely accurate, any benchmark should be careful to avoid compiler optimisations eliminating the function under test and artificially lowering the run time of the benchmark.

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
}

Source

以下页面也很有用。

Compiler And Runtime Optimizations

另一个有趣的读物是

One other interesting flag is -N, which will disable the optimisation pass in the compiler.

Source1 Source2

我不是 100% 确定但以下应该禁用优化?需要有经验的人来确认一下。

go test -gcflags=-N -bench=.