我编写了一个简单的程序,该程序对包含在一个巨大的切片中的所有值进行OR运算。当我使用10倍大的切片时,我预计会有10倍的性能下降。但是,在执行提供的测试时,存在巨大的性能差距。程序输出如下:
oadam@oadam-Latitude-E6510:~/$ go test -bench .
testing: warning: no tests to run
PASS
BenchmarkLittle 2000000000 0.11 ns/op
BenchmarkBig 1 2417869962 ns/op
ok _/home/oadam/ 5.048s
代码
package main
import (
"math/rand"
"testing"
)
const (
little = 5000000
big = 50000000
)
var a = make([]uint32, big)
func benchOR(b *testing.B, l int) {
for i := 0; i < l; i++ {
a[i] = rand.Uint32()
}
var result uint32
for i := 0; i < l; i++ {
result |= a[i]
}
}
func BenchmarkLittle(b *testing.B) {
benchOR(b, little)
}
func BenchmarkBig(b *testing.B) {
benchOR(b, big)
}
编辑:必须是go test -bench中的错误。使用手动计时我不会重现
package main
import (
"log"
"math/rand"
"time"
)
const (
little = 5000000
big = 50000000
)
var a = make([]uint32, big)
func initA(l int) {
for i := 0; i < l; i++ {
a[i] = rand.Uint32()
}
}
func test(l int) uint32 {
var result uint32
for i := 0; i < l; i++ {
result |= a[i]
}
return result
}
func main() {
initA(little)
var before = time.Now()
test(little)
log.Println(time.Since(before))
initA(big)
var before2 = time.Now()
test(big)
log.Println(time.Since(before2))
}
答案 0 :(得分:5)
问题在于您没有使用b.N
,它会告诉您运行基准测试的次数。此外,如果您只想对ORing进行基准测试,您可能只需要初始化一次数组,或者至少调用b.ResetTimer()
,这样就不会计算初始化。
这是我最终得到的结果,它给出了预期的结果:
package main
import (
"math/rand"
"testing"
)
const (
little = 5000000
big = 50000000
)
var a = make([]uint32, big)
func init() {
for i := 0; i < big; i++ {
a[i] = rand.Uint32()
}
}
func benchOR(b *testing.B, l int) {
var result uint32
for _, u := range a[:l] {
result |= u
}
}
func BenchmarkLittle(b *testing.B) {
for i := 0; i < b.N; i++ {
benchOR(b, little)
}
}
func BenchmarkBig(b *testing.B) {
for i := 0; i < b.N; i++ {
benchOR(b, big)
}
}
我的结果:
BenchmarkLittle 500 3222064 ns/op
BenchmarkBig 50 32268023 ns/op
答案 1 :(得分:2)
我不认为这是一个错误。我修改了你的代码,这就是我得到的:
% go test -bench=.
testing: warning: no tests to run
PASS
BenchmarkLittle 2000000000 0.00 ns/op
BenchmarkBig 2000000000 0.02 ns/op
ok _/Users/kavu/TMP/becnh_or 12.659s
代码:
package main
import (
"math/rand"
"testing"
)
const (
little = 5000000
big = 50000000
)
func benchOR(a []uint32, l int) (result uint32) {
for i := 0; i < l; i++ {
result |= a[i]
}
return result
}
func BenchmarkLittle(b *testing.B) {
var a = make([]uint32, big)
for i := 0; i < little; i++ {
a[i] = rand.Uint32()
}
b.ResetTimer()
benchOR(a, little)
}
func BenchmarkBig(b *testing.B) {
var a = make([]uint32, big)
for i := 0; i < big; i++ {
a[i] = rand.Uint32()
}
b.ResetTimer()
benchOR(a, big)
}
您可以对b.ResetTimer()
和benchOR(a, big)
内容进行评论,看看会发生什么。您也可以尝试big
常量。某处10000000
它足够快,即使没有重置计时器也是如此。因此,使用rand.Uint32
生成一个大切片会减慢所有内容。