2014-02-10 26 views
2

我寫了一個簡單的程序,將OR中包含的所有值都包含在一個巨大的切片中。當我使用10倍大的切片時,我預計會有10倍的性能下降。但是在執行提供的測試時,性能差距很大。該程序的輸出如下:OR取決於陣列大小的突然減速

[email protected]:~/$ 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) 
} 

編輯:一定要在去測試-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)) 

} 

回答

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

你應該叫[b.SetBytes](http://golang.org/ pkg/testing /#B.SetBytes),那麼基準測試也會顯示MB/s,這將會提供很多信息! –

+0

不知道b.N。下一次我會在問我的問題之前閱讀完整的文檔。謝謝 ! – olivieradam666

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生成一個大片會減慢一切。