在学习Go的过程中,我看到您可以使用fmt.Println(testing.Benchmark(BenchmarkFunction))对函数进行基准测试,并设置了以下设置:
func BenchmarkFunction(b *testing.B) {
n := 42
for i := 0; i < b.N; i++ {
_ = Function(n)
}
}但是,由于您要对每个方法执行此操作的每个基准测试都会重复BenchmarkFunction代码(因此,就DRY而言,这是一种代码气味),是否有一种方法可以使用闭包(或以其他方式)重写此代码,以便可以重写函数的基准测试,如下所示:
fmt.println(test.BenchmarkMyFunction(MyFunction(parameters...)))并添加到我的代码或testing库中?
发布于 2013-06-04 22:51:40
实际上,这不是在Go中进行基准测试的正确方式。
实际的标准是将您的基准测试代码放入名称为BenchmarkXXX的函数中,其中XXX是您喜欢的任何名称。然后在定义这些文件的包上运行go test -bench=.。go test正在为您运行所有基准测试。
如果您有类似的基准测试,但参数略有不同,则可以编写一个通用基准测试函数,该函数仅供所有其他基准测试调用:
func genericBenchmarkFoo(b *testing.B, param int) { ... }然后为每个特定的基准测试编写一个样板函数:
func BenchmarkFoo1(b *testing.B) { genericBenchmarkFoo(b, 1) }
func BenchmarkFoo2(b *testing.B) { genericBenchmarkFoo(b, 2) }
func BenchmarkFoo3(b *testing.B) { genericBenchmarkFoo(b, 3) }
func BenchmarkFoo4(b *testing.B) { genericBenchmarkFoo(b, 4) }你可以在我写的这个package中找到这个模式的一个例子。
当然,这并不是很好,但我担心没有更容易的解决方案。然而,找到一小组代表您想要做的事情的基准测试是一种干净的编码。
发布于 2013-06-05 05:36:08
这是一个真正的、简单的DRY Go基准测试,它使用闭包。我想知道各种Substr函数的性能是如何随子字符串的大小(hi - lo)而变化的。
package main
import (
"fmt"
"strings"
"testing"
)
func Substr1(str string, lo, hi int) string {
return string([]byte(str[lo:hi]))
}
func Substr2(str string, lo, hi int) string {
sub := str[lo:hi]
return (sub + " ")[:len(sub)]
}
func Substr3(str string, lo, hi int) string {
sub := str[lo:hi]
if len(sub) == 0 {
return ""
}
return sub[0:1] + sub[1:]
}
var substrFunctions = []struct {
name string
function func(str string, lo, hi int) string
}{
{"Substr1", Substr1},
{"Substr2", Substr2},
{"Substr3", Substr3},
}
var substrBenchmarks = []struct {
name string
strLen, subLo, subHi int
}{
{"Zero ", 1, 1, 1},
{"Small ", 4, 1, 4},
{"Medium", 256, 1, 256},
{"Large ", 4096, 1, 4096},
}
func BenchmarkSubstrSize() {
fmt.Println("BenchmarkSubstrSize:")
for _, benchmark := range substrBenchmarks {
str := strings.Repeat("abc", benchmark.strLen)
for _, function := range substrFunctions {
benchmarkFunc := func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
function.function(str, benchmark.subLo, benchmark.subHi)
}
b.StopTimer()
}
results := testing.Benchmark(benchmarkFunc)
fmt.Println(benchmark.name, function.name, results)
}
}
}
func main() {
BenchmarkSubstrSize()
}输出:
BenchmarkSubstrSize:
Zero Substr1 50000000 54.8 ns/op
Zero Substr2 100000000 19.6 ns/op
Zero Substr3 500000000 6.66 ns/op
Small Substr1 20000000 95.7 ns/op
Small Substr2 50000000 70.4 ns/op
Small Substr3 50000000 70.1 ns/op
Medium Substr1 5000000 380 ns/op
Medium Substr2 10000000 229 ns/op
Medium Substr3 10000000 213 ns/op
Large Substr1 500000 4290 ns/op
Large Substr2 1000000 2007 ns/op
Large Substr3 1000000 2275 ns/op发布于 2013-06-04 22:56:10
我不确定这是否可以被认为是一种收获:
package main
import (
"fmt"
"testing"
)
func f1(n int) (s int) {
for i := 0; i < n; i++ {
s += i
}
return
}
func f2(n int) (s int) {
for i := 0; i < n; i++ {
s += 2 * i
}
return
}
func bench(f func()) func(b *testing.B) {
return func(b *testing.B) {
for i := 0; i < b.N; i++ {
f()
}
}
}
func main() {
fmt.Printf("%v\n", testing.Benchmark(bench(func() { f1(42) })))
fmt.Printf("%v\n", testing.Benchmark(bench(func() { f2(24) })))
}输出:
(16:55) jnml@fsc-r550:~/src/tmp/SO/16920669$ go run main.go
50000000 68.4 ns/op
50000000 35.8 ns/op
(16:55) jnml@fsc-r550:~/src/tmp/SO/16920669$ https://stackoverflow.com/questions/16920669
复制相似问题