![](/img/trans.png)
[英]Does Golang do any conversion when casting a byte slice to a string?
[英]When golang does allocation for string to byte conversion
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)
}
}
測試結果:
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
如果string長,為什么在BenchmarkHashingWithNew900000000情況下有分配,而string小時為什么沒有分配。
Sum32: https ://gowalker.org/github.com/spaolacci/murmur3
我正在使用go1.6
您的基准測試正在觀察Golang編譯器(版本1.8)的奇怪優化。
您可以在此處查看Dmitry Dvyukov的PR
https://go-review.googlesource.com/c/go/+/3120
不幸的是,這是很久以前的事情,當時使用C語言編寫編譯器時,我不確定在當前的編譯器中哪里可以找到優化。 但是我可以確認它仍然存在,並且Dmitry的PR描述是准確的。
如果您想要一組更清晰的自包含基准來證明這一點,我這里有一個要點。
https://gist.github.com/fmstephe/f0eb393c4ec41940741376ab08cbdf7e
如果僅查看第二個基准BenchmarkHashingWithNew900000000
我們可以清楚地看到它應該“分配”的位置。
bytStr := []byte(testString)
該行必須將testString
的內容復制到新的[]byte
。 然而,在這種情況下,編譯器可以看到bytStr
從未之后再次使用Sum32
的回報。 因此,可以在堆棧上分配它。 但是,由於字符串可以任意大,所以將堆棧分配的string
或[]byte
的限制設置為32個[]byte
。
值得一提的是這個小技巧,因為如果基准字符串都很短,很容易就讓自己相信一些代碼沒有分配。
當您將某些內容寫入byte.Buffer
,它將根據需要分配內存。 當您調用byte.Buffer.Reset
,不會釋放該內存,而是將其保留以供以后重用。 而您的代碼正是這樣做的。 它將緩沖區標記為空,然后再次填充。
其實, 有一些分配的事,但迭代5000次的時候,實在是微不足道。 但是,如果將bufByte
的聲明bufByte
for
循環中,則會得到一些分配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.