代码之家  ›  专栏  ›  技术社区  ›  nos

如何在高朗基准测试中正确地启动和停止时间?

  •  3
  • nos  · 技术社区  · 6 年前

    我写了一个基准测试两个Fibonacci数生成器的速度,源代码是 here on github .

    func BenchmarkFib(b *testing.B) {
        fibFuncs := []struct {
            name string
            f    func(int) int
        }{
            {"recursive", fibRecu},
            {"iterative", fibIter},
        }
        for _, fibFunc := range fibFuncs {
            // calculate k'th Fibonacci number
            for k := 10; k < 1001; k *= 10 {
                b.Run(fmt.Sprintf("%s Fib %v", fibFunc.name, k), func(b *testing.B) {
                    for n := 0; n < b.N; n++ {
                        //                  b.StopTimer()
                        // reset the memo
                        memo = map[int]int{0: 0, 1: 1, 2: 1}
                        //                  b.StartTimer()
                        fibFunc.f(k)
                    }
                })
            }
        }
    }
    

    nos (master) fibonacci $ go test -bench .
    goos: linux
    goarch: amd64
    pkg: github.com/nosarthur/dynamicP/fibonacci
    BenchmarkFib/recursive_Fib_10-4                  1000000              1256 ns/op
    BenchmarkFib/recursive_Fib_100-4                  100000             18256 ns/op
    BenchmarkFib/recursive_Fib_1000-4                  10000            206109 ns/op
    BenchmarkFib/iterative_Fib_10-4                 10000000               218 ns/op
    BenchmarkFib/iterative_Fib_100-4                 5000000               292 ns/op
    BenchmarkFib/iterative_Fib_1000-4                2000000               881 ns/op
    PASS
    ok      github.com/nosarthur/dynamicP/fibonacci 12.208s
    

    不过,我补充说 b.StopTime() b.StartTime() 排除重置备忘的时间。在这两行未注释的情况下,基准将挂起,部分输出为

    nos (master *) fibonacci $ go test -bench .
    goos: linux
    goarch: amd64
    pkg: github.com/nosarthur/dynamicP/fibonacci
    BenchmarkFib/recursive_Fib_10-4                  1000000              2139 ns/op
    BenchmarkFib/recursive_Fib_100-4                  100000             24775 ns/op
    BenchmarkFib/recursive_Fib_1000-4                   5000            239197 ns/op
    BenchmarkFib/iterative_Fib_10-4                 ^Csignal: interrupt
    FAIL    github.com/nosarthur/dynamicP/fibonacci 269.067s
    

    1 回复  |  直到 6 年前
        1
  •  1
  •   jlovison    6 年前

    正在发生的是你的功能是 真正地 很快,特别是在迭代函数的情况下,您的映射重置(以及 StartTimer StopTimer

    所以当你打电话的时候 计时器 它将基准测试的内部跟踪持续时间设置为仅运行该函数所需的时间。猜猜它是如何估计在指定的基准时间内要运行多少个迭代的?是的,你猜对了-内部持续时间。

    我的建议-不要用 StartTimer/StopTimer 在这种情况下,只需在测试中添加第三次运行,即不执行操作——基本上:

    {"baseline", func(int) int {return 0}},
    

    然后从另外两个集合中减去这个函数的次数,就可以估计出分配与函数本身的ns/op之比。

    BenchmarkFib/baseline_Fib_10-2           5000000           357 ns/op
    BenchmarkFib/baseline_Fib_100-2          5000000           327 ns/op
    BenchmarkFib/baseline_Fib_1000-2         5000000           310 ns/op
    BenchmarkFib/recursive_Fib_10-2          1000000          1659 ns/op
    BenchmarkFib/recursive_Fib_100-2           50000         24898 ns/op
    BenchmarkFib/recursive_Fib_1000-2           5000        301771 ns/op
    BenchmarkFib/iterative_Fib_10-2          5000000           333 ns/op
    BenchmarkFib/iterative_Fib_100-2         3000000           394 ns/op
    BenchmarkFib/iterative_Fib_1000-2        1000000          1052 ns/op
    PASS
    ok      _/tmp/dynamicP/fibonacci    15.305s