【问题标题】:Benchmark Go code and goroutines基准 Go 代码和 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的值,不行吗?

标签: go benchmarking goroutine


【解决方案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 交给了调度器,得到了时间,然后结束了程序。没多久!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 2010-12-16
    • 1970-01-01
    相关资源
    最近更新 更多