-
-
Save fmstephe/f0eb393c4ec41940741376ab08cbdf7e to your computer and use it in GitHub Desktop.
Subtle allocation behaviour converting from string to byte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "testing" | |
var bytesHole []byte | |
var intHole int | |
// This tests a compiler optimisation described very clearly in this PR | |
// https://go-review.googlesource.com/c/go/+/3120 | |
func BenchmarkStringBytes32(b *testing.B) { | |
str := makeString(32) | |
b.ReportAllocs() | |
for i := 0; i < b.N; i++ { | |
convertToBytes(str) | |
} | |
} | |
func BenchmarkStringBytes33(b *testing.B) { | |
str := makeString(33) | |
b.ReportAllocs() | |
for i := 0; i < b.N; i++ { | |
convertToBytes(str) | |
} | |
} | |
func BenchmarkStringBytes32Count(b *testing.B) { | |
str := makeString(32) | |
b.ReportAllocs() | |
for i := 0; i < b.N; i++ { | |
countStr(str) | |
} | |
} | |
func BenchmarkStringBytes33Count(b *testing.B) { | |
str := makeString(33) | |
b.ReportAllocs() | |
for i := 0; i < b.N; i++ { | |
countStr(str) | |
} | |
} | |
func makeString(length int) string { | |
bs := []byte{} | |
for i := 0; i < length; i++ { | |
bs = append(bs, byte(i)) | |
} | |
return string(bs) | |
} | |
// Here the []byte escapes, and will always be allocated to the heap regardless of size | |
//go:noinline | |
func convertToBytes(s string) { | |
bytesHole = []byte(s) | |
} | |
// Here the []byte does not escape, and can be stack allocated if it's <= 32 bytes | |
//go:noinline | |
func countStr(s string) { | |
count([]byte(s)) | |
} | |
//go:noinline | |
func count(bs []byte) { | |
for _, b := range bs { | |
intHole += int(b) | |
} | |
} | |
/* | |
BenchmarkStringBytes32-4 30000000 47.1 ns/op 32 B/op 1 allocs/op | |
BenchmarkStringBytes33-4 30000000 54.1 ns/op 48 B/op 1 allocs/op | |
BenchmarkStringBytes32Count-4 20000000 68.2 ns/op 0 B/op 0 allocs/op | |
BenchmarkStringBytes33Count-4 10000000 110 ns/op 48 B/op 1 allocs/op | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment