2016-07-24 74 views
4
var testString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
//var testString = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" 
func BenchmarkHashing900000000(b *testing.B){ 
    var bufByte = bytes.Buffer{} 
    for i := 0; i < b.N ; i++{ 
     bufByte.WriteString(testString) 
     Sum32(bufByte.Bytes()) 
     bufByte.Reset() 
    } 
} 

func BenchmarkHashingWithNew900000000(b *testing.B){ 
    for i := 0; i < b.N ; i++{ 
     bytStr := []byte(testString) 
     Sum32(bytStr) 
    } 
} 

測試結果:當golang不分配字符串字節轉換

With testString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
BenchmarkHashing900000000-4   50000000   35.2 ns/op   0 B/op   0 allocs/op 
BenchmarkHashingWithNew900000000-4 50000000   30.9 ns/op   0 B/op   0 allocs/op 

With testString = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" 
BenchmarkHashing900000000-4   30000000   46.6 ns/op   0 B/op   0 allocs/op 
BenchmarkHashingWithNew900000000-4 20000000   73.0 ns/op  64 B/op   1 allocs/op 

爲什麼在BenchmarkHashingWithNew900000000的情況下分配時字符串很長,但沒有配置字符串時小。
Sum32:https://gowalker.org/github.com/spaolacci/murmur3
當你寫的東西變成byte.Buffer我使用go1.6

回答

-1

,根據需要分配內存。當您致電byte.Buffer.Reset時,該內存不會釋放,而是保留以備後用。而你的代碼就是這麼做的。它將緩衝區標記爲空,然後再次填充它。

其實有的分配正在進行,但迭代50000000次時,可以忽略不計。但是如果您將bufByte的聲明移動到for循環中,您將獲得一些分配。

+0

這是我所期望的。除了上面的基準線顯示較小的字符串,兩種情況下都沒有分配。但是,對於更大的字符串,它的行爲如預期。 –

+0

你應該看看編譯的代碼。 '去測試-c'然後'去工具objdump -s'BenchmarkHashing'main.test.exe'。 –

+0

@VishalKumar實際上,在'bytes.Buffer'版本的_either_情況下你不應該看到一個分配。 Bytes.Buffer在其結構中具有一個內置的64字節數組,用於處理沒有(額外)分配的小數據集,並且每個寫操作都不超過64個字節。如果你將'bufByte.Reset()'移到for循環之外,我感覺你會看到更公平的結果。 – Kaedys

0

你的基準正在觀察Golang編譯器(版本1.8)的一個奇怪的優化。

你可以看到從梅德Dvyukov這裏的PR

https://go-review.googlesource.com/c/go/+/3120

不幸的是,從很久以前,當編譯器是用C寫的,我不知道在哪裏可以找到的最優化當前編譯器。但是我可以證實它仍然存在,德米特里的公關描述是準確的。

如果你想要一套更明確的自包含的基準來證明這一點,我在這裏有一個要點。

https://gist.github.com/fmstephe/f0eb393c4ec41940741376ab08cbdf7e

如果我們在第二次基準BenchmarkHashingWithNew900000000只能看,我們可以看到一個清晰的斑點它「應該」分配。

bytStr := []byte(testString) 

此行必須的testString內容複製到一個新的[]byte。但是在這種情況下,編譯器可以看到返回後bytStr從不再使用。因此它可以在堆棧上分配。但是,由於字符串可以是任意大的,對於分配的堆棧string[]byte,限制設置爲32個字節。

值得注意這個小技巧,因爲如果你的基準測試字符串都很短,可能很容易欺騙自己相信某些代碼沒有分配。