基准 Go 代码和 goroutines
Posted
技术标签:
【中文标题】基准 Go 代码和 goroutines【英文标题】:Benchmark Go code and goroutines 【发布时间】:2016-02-05 19:20:57 【问题描述】:我想对一个函数进行基准测试:test()
,使用不同数量的线程处理它。
没有 goroutine:
var t1 = time.Now()
test()
var elapsed1 = time.Since(t1)
1 ns / 操作
使用 goroutine:
runtime.GOMAXPROCS(1)
var t1 = time.Now()
go test()
var elapsed1 = time.Since(t1)
1.10^-6 ns / 操作
我的测试功能:
func test()
for i := 0; i < 1000000000; i++
float_result = f1 + f2
float_result = f1 - f2
float_result = f1 * f2
float_result = f1 / f2
float_result = f1 + f2
float_result = f1 - f2
float_result = f1 * f2
float_result = f1 / f2
float_result = f1 + f2
float_result = f1 - f2
float_result = f1 * f2
float_result = f1 / f2
float_result = f1 + f2
float_result = f1 - f2
float_result = f1 * f2
float_result = f1 / f2
float_result = f1 + f2
float_result = f1 - f2
float_result = f1 * f2
float_result = f1 / f2
在这种情况下,当我使用 goroutine 时,test() 函数的基准测试是否良好?
如何达到 0.001ns/操作?它看起来太快了。 (2.5GHz 英特尔酷睿 i7)
使用带有runtime.GOMAXPROCS(n)
的goroutines 是否等同于使用n 个线程?
【问题讨论】:
任何语言的任何体面的编译器都会丢弃循环中的几乎所有代码,因为您的 float_result 值从未使用过。您需要将其写入输出或文件。 即使你在最后使用了 float_result,也只有最后一行会运行,因为所有其他行都被覆盖了。 我想做很多操作,不多次使用同一个变量怎么办?如果我做var = f1 + f2 + f3 + f4,编译后直接写f1 + f2 + f3 + f4的值,不行吗? 【参考方案1】:您测量的不是test()
运行的时间,而是使用go test()
调用/创建新goroutine 所需的时间。
您需要等待 goroutine 完成,例如使用 sync.Waitgroup。
// somewhere in your main package
var wg sync.WaitGroup
func test()
// first lines in test() should be
wg.Add(1)
defer wg.Done()
...
// benchmark
runtime.GOMAXPROCS(1)
var t1 = time.Now()
go test()
wg.Wait()
var elapsed1 = time.Since(t1)
【讨论】:
【参考方案2】:您正在尝试对小到以测量误差为主的事物进行基准测试。您的基准测试迭代应该进行调整,直到基准功能持续足够长的时间以可靠地计时。您的基准测试应该运行大约一秒钟才有意义。
【讨论】:
即使我在test()
函数中有 100 亿个循环,我也有相同的结果。而且,有了runtime.GOMAXPROCS(1)
,应该不会比没有goroutine那么大吧?
@Nico401:向我们展示您的测试功能:How to create a Minimal, Complete, and Verifiable example.。
我做到了,我相信你会认出它:)
@Nico401:“与常规调用不同,程序执行不会等待调用的函数完成。” Go statements。所以你把 goroutine 交给了调度器,得到了时间,然后结束了程序。没多久!以上是关于基准 Go 代码和 goroutines的主要内容,如果未能解决你的问题,请参考以下文章