Why does BenchmarkTest3 in go 1.22 still have memory allocation? My local test doesn’t have it
在2023年11月27日星期一 UTC+8 23:14:03<peterGo> 写道: > > Assigning Benchmark results to package variables: > > var ( > str string > byt []byte > ) > > BenchmarkString > str = string(byteSli) > > BenchmarkUnsafe > str = *(*string)(unsafe.Pointer(&byteSli)) > > BenchmarkByteStyle > byt = []byte(str) > > BenchmarkWithUnsafe > byt = *(*[]byte)(unsafe.Pointer(&bh)) > > $ go1.21 test nuts_test.go -run=! -bench=. -benchmem > BenchmarkTest1-12 22507272 50.72 ns/op 192 B/op 1 allocs/op > BenchmarkTest2-12 27105592 49.92 ns/op 192 B/op 1 allocs/op > BenchmarkTest3-12 25006983 41.32 ns/op 160 B/op 1 allocs/op > BenchmarkTest4-12 1000000000 1.158 ns/op 0 B/op 0 allocs/op > > $ go1.22 test nuts_test.go -run=! -bench=. -benchmem > BenchmarkTest1-12 17386624 65.79 ns/op 192 B/op 1 allocs/op > BenchmarkTest2-12 18603463 62.30 ns/op 192 B/op 1 allocs/op > BenchmarkTest3-12 23741634 57.76 ns/op 160 B/op 1 allocs/op > BenchmarkTest4-12 1000000000 1.157 ns/op 0 B/op 0 allocs/op > > peter > > On Monday, November 27, 2023 at 7:12:54 AM UTC-5 fliter wrote: > >> It seems that go 1.22 has optimized the implementation of string to byte >> slicing and no longer requires memory allocation. >> >> >> But why not optimize byte slicing to string conversion together? >> >> >> ```go >> package main >> >> import ( >> "reflect" >> "testing" >> "unsafe" >> ) >> >> >> func BenchmarkString(b *testing.B) { >> byteSli := []byte{123, 34, 100, 101, 102, 97, 117, 108, 116, 34, 58, 123, >> 34, 99, 111, 109, 109, 111, 110, 34, 58, 123, 34, 112, 101, 116, 34, 58, >> 123, 34, 102, 105, 118, 101, 34, 58, 34, 230, 150, 145, 230, 150, 145, 34, >> 44, 34, 102, 111, 117, 114, 34, 58, 34, 231, 154, 174, 231, 147, 156, 231, >> 147, 156, 34, 44, 34, 111, 110, 101, 34, 58, 34, 229, 188, 165, 229, 188, >> 165, 230, 135, 181, 34, 44, 34, 116, 104, 114, 101, 101, 34, 58, 34, 229, >> 145, 134, 229, 145, 134, 34, 44, 34, 116, 119, 111, 34, 58, 34, 233, 187, >> 132, 230, 169, 153, 230, 169, 153, 34, 125, 44, 34, 114, 101, 108, 97, 116, >> 105, 111, 110, 34, 58, 123, 34, 102, 97, 116, 104, 101, 114, 34, 58, 34, >> 99, 117, 105, 120, 120, 120, 120, 120, 120, 120, 34, 44, 34, 109, 111, 116, >> 104, 101, 114, 34, 58, 34, 121, 105, 110, 120, 120, 120, 120, 120, 34, 44, >> 34, 119, 105, 102, 101, 34, 58, 34, 112, 101, 110, 103, 120, 120, 34, 125, >> 125, 125, 125} >> >> _ = string(byteSli) >> >> } >> >> func BenchmarkUnsafe(b *testing.B) { >> byteSli := []byte{123, 34, 100, 101, 102, 97, 117, 108, 116, 34, 58, 123, >> 34, 99, 111, 109, 109, 111, 110, 34, 58, 123, 34, 112, 101, 116, 34, 58, >> 123, 34, 102, 105, 118, 101, 34, 58, 34, 230, 150, 145, 230, 150, 145, 34, >> 44, 34, 102, 111, 117, 114, 34, 58, 34, 231, 154, 174, 231, 147, 156, 231, >> 147, 156, 34, 44, 34, 111, 110, 101, 34, 58, 34, 229, 188, 165, 229, 188, >> 165, 230, 135, 181, 34, 44, 34, 116, 104, 114, 101, 101, 34, 58, 34, 229, >> 145, 134, 229, 145, 134, 34, 44, 34, 116, 119, 111, 34, 58, 34, 233, 187, >> 132, 230, 169, 153, 230, 169, 153, 34, 125, 44, 34, 114, 101, 108, 97, 116, >> 105, 111, 110, 34, 58, 123, 34, 102, 97, 116, 104, 101, 114, 34, 58, 34, >> 99, 117, 105, 120, 120, 120, 120, 120, 120, 120, 34, 44, 34, 109, 111, 116, >> 104, 101, 114, 34, 58, 34, 121, 105, 110, 120, 120, 120, 120, 120, 34, 44, >> 34, 119, 105, 102, 101, 34, 58, 34, 112, 101, 110, 103, 120, 120, 34, 125, >> 125, 125, 125} >> >> _ = *(*string)(unsafe.Pointer(&byteSli)) >> } >> >> func BenchmarkByteStyle(b *testing.B) { >> >> str := >> `{"default":{"common":{"pet":{"five":"aa","four":"bb","one":"cc","three":"dd","two":"黄ee"},"relation":{"father":"ff","mother":"mm","wife":"ww"}}}}` >> >> _ = []byte(str) >> >> } >> >> func BenchmarkWithUnsafe(b *testing.B) { >> >> str >> := >> `{"default":{"common":{"pet":{"five":"aa","four":"bb","one":"cc","three":"dd","two":"黄ee"},"relation":{"father":"ff","mother":"mm","wife":"ww"}}}}` >> >> sh := (*reflect.StringHeader)(unsafe.Pointer(&str)) >> bh := reflect.SliceHeader{ >> Data: sh.Data, >> Len: sh.Len, >> Cap: sh.Len, >> } >> _ = *(*[]byte)(unsafe.Pointer(&bh)) >> >> } >> ``` >> >> ```bench_test.go >> package main >> >> import ( >> "testing" >> ) >> >> >> func BenchmarkTest1(b *testing.B) { >> for i := 0; i < b.N; i++ { >> BenchmarkString(b) >> } >> } >> >> func BenchmarkTest2(b *testing.B) { >> for i := 0; i < b.N; i++ { >> BenchmarkUnsafe(b) >> } >> } >> >> func BenchmarkTest3(b *testing.B) { >> for i := 0; i < b.N; i++ { >> BenchmarkByteStyle(b) >> } >> } >> >> func BenchmarkTest4(b *testing.B) { >> for i := 0; i < b.N; i++ { >> BenchmarkWithUnsafe(b) >> } >> } >> ``` >> >> when go version is 1.21 >> >> ```shell >> go version >> go version go1.21.0 darwin/arm64 >> >> goos: darwin >> goarch: arm64 >> pkg: bc >> BenchmarkTest1-8 37078008 32.45 ns/op 192 >> B/op 1 allocs/op >> BenchmarkTest2-8 144106840 9.181 ns/op 0 >> B/op 0 allocs/op >> BenchmarkTest3-8 38973375 28.94 ns/op 192 >> B/op 1 allocs/op >> BenchmarkTest4-8 1000000000 0.3130 ns/op 0 >> B/op 0 allocs/op >> PASS >> ok bc 6.038s >> >> ``` >> >> >> >> when go version is 1.22 >> >> ```shell >> go version >> go version devel go1.22-631a6c2abf Fri Nov 17 23:34:11 2023 +0000 >> darwin/arm64 >> >> >> go test -test.bench=".*" -benchmem >> goos: darwin >> goarch: arm64 >> pkg: bc >> BenchmarkTest1-8 35727334 33.51 ns/op 192 >> B/op 1 allocs/op >> BenchmarkTest2-8 147172425 8.157 ns/op 0 >> B/op 0 allocs/op >> BenchmarkTest3-8 1000000000 0.3136 ns/op 0 >> B/op 0 allocs/op >> BenchmarkTest4-8 1000000000 0.3153 ns/op 0 >> B/op 0 allocs/op >> PASS >> ok bc 5.095s >> ``` >> >> >> >> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/2b93d4aa-1aca-4da9-93cb-bf836b250b6bn%40googlegroups.com.