使用testing.Benchmark不会产生任何输出。

huangapple go评论78阅读模式
英文:

Using testing.Benchmark does not produce any output

问题

我正在使用testing.Benchmark来手动运行一些基准测试,但结果对象始终为空。

我是否漏掉了什么?

以下是一个示例:

package main

import "testing"

func main() {

    result := testing.Benchmark(func(parentB *testing.B) {
        parentB.Run("example", func(b *testing.B) {
            for n := 0; n < b.N; n++ {
                println("ok")
            }
        })
    })

    println(result.String())

}

这将打印出ok多次,然后是0 0 ns/op,但基准测试显然确实运行了一些内容。

英文:

I'm using testing.Benchmark to manually run a couple benchmarks but the result object is always empty.

Am I missing something here?

Here's an example:

package main

import &quot;testing&quot;

func main() {

    result := testing.Benchmark(func(parentB *testing.B) {
	    parentB.Run(&quot;example&quot;, func(b *testing.B) {
		    for n := 0; n &lt; b.N; n++ {
			    println(&quot;ok&quot;)
		    }
	    })
    })

	println(result.String())

}

This will print ok a couple times and then 0 0 ns/op but the benchmark clearly did run something.

答案1

得分: 3

我认为你做得很对。testing.Benchmark() 的文档中写道:

> Benchmark 用于对单个函数进行基准测试。适用于创建不使用 "go test" 命令的自定义基准测试。
>
> 如果函数 f 调用了 Run,那么结果将是按顺序运行所有不调用 Run 的子基准测试的估计时间。

查看实现代码(Go 1.7.4):

func Benchmark(f func(b *B)) BenchmarkResult {
    b := &amp;B{
        common: common{
            signal: make(chan bool),
            w:      discard{},
        },
        benchFunc: f,
        benchTime: *benchTime,
    }
    if !b.run1() {
        return BenchmarkResult{}
    }
    return b.run()
}

其中这一行:

    if !b.run1() {
        return BenchmarkResult{}
    }

b.run1() 用于运行传入的函数一次,并检测是否有子基准测试。你的函数有子基准测试。它返回一个布尔值,表示是否需要进行更多运行。在 run1() 函数内部:

if b.hasSub || b.finished {
    // ...
    return true
}

它正确地告诉函数有子基准测试,并且 Benchmark() 函数简单地返回一个空的 BenchmarkResult

    if !b.run1() {
        return BenchmarkResult{}
    }

我相信这要么是一个 bug(或者说是“不完整”的功能),要么是文档有误。我建议在这里提交一个问题:https://github.com/golang/go/issues

英文:

I think you are doing everything right. Doc of testing.Benchmark() says:

> Benchmark benchmarks a single function. Useful for creating custom benchmarks that do not use the "go test" command.
>
> If f calls Run, the result will be an estimate of running all its subbenchmarks that don't call Run in sequence in a single benchmark.

Looking into the implementation (Go 1.7.4):

func Benchmark(f func(b *B)) BenchmarkResult {
    b := &amp;B{
        common: common{
            signal: make(chan bool),
            w:      discard{},
        },
        benchFunc: f,
        benchTime: *benchTime,
    }
    if !b.run1() {
        return BenchmarkResult{}
    }
    return b.run()
}

This line:

    if !b.run1() {
        return BenchmarkResult{}
    }

b.run1() is supposed to run your passed function once, and detect if it has sub-benchmarks. Yours has. It returns a bool whether more runs are needed. Inside run1():

if b.hasSub || b.finished {
    // ...
    return true
}

It properly tells it has sub-benchmark, and Benchmark() –with noble simplicity– just returns an empty BenchmarkResult:

    if !b.run1() {
        return BenchmarkResult{}
    }

I do believe that either this is a bug (or rather "incomplete" feature), or doc is incorrect. I suggest to file an issue here: https://github.com/golang/go/issues

答案2

得分: 1

编辑答案以澄清:

我猜你是使用"go run"来运行测试。这样不会产生任何结果。为了按照代码的原样运行,你需要使用"go test -bench=.",我认为这样应该可以工作。
文件必须命名为"test_xxx.go",其中xxx可以是任何你想要的。

如果你稍微重构一下代码,它可以作为一个单函数基准测试运行:

package main

import "testing"

func main() {
    myTest()
}

func myTest() {
    fn := func(b *testing.B) {
        for n := 0; n < b.N; n++ {
            println("ok")
        }
    }
    result := testing.Benchmark(fn)

    println(result.String())
}
英文:

Eddited the answer to clarify:

My guess is that you are using go run to run the test. That will not produce any result. In order to run the code exatly as it is written you need to use
go test -bench=. and I think it should work.
The file must be named test_xxx.go where xxx is whatever you want.

If you restucture you code a litle bit it can be run as a single function benchmark:

package main

import &quot;testing&quot;

func main() {
	myTest()
}

func myTest() {
	fn := func(b *testing.B) {
		for n := 0; n &lt; b.N; n++ {
			println(&quot;ok&quot;)
		}
	}
	result := testing.Benchmark(fn)

	println(result.String())
}

huangapple
  • 本文由 发表于 2017年1月26日 05:24:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/41861918.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定