英文:
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 "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())
}
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 := &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 := &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 "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())
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论