Higher performance UnsafeStringToSlice
https://github.com/cloudwego/netpoll/blob/44a7f98a7da7ad700461433cdf4a434a0f9aeeb5/nocopy.go#L279
建议用如下函数替换UnsafeStringToSlice,经过benchmark测试,性能提高约30%左右,代码也更优雅
func UnsafeStringToSlice2(s string) []byte {
return *(*[]byte)(unsafe.Pointer(
&struct {
string
int
}{s, len(s)},
))
}
### 测试详情
go test -bench . -benchmem goos: darwin goarch: arm64 pkg: gitlab-vywrajy.zd100.net/slice/service BenchmarkToSlice/UnsafeStringToSlice-8 737677520 1.542 ns/op 0 B/op 0 allocs/op BenchmarkToSlice/UnsafeStringToSlice2-8 1000000000 1.188 ns/op 0 B/op 0 allocs/op PASS ok gitlab-vywrajy.zd100.net/slice/service 2.928s
### 相关测试代码
package service
import (
"reflect"
"testing"
"unsafe"
)
func BenchmarkToSlice(b *testing.B) {
a := "hello world"
var bs []byte
b.Run("UnsafeStringToSlice", func(b *testing.B) {
for i := 0; i < b.N; i++ {
bs = UnsafeStringToSlice(a)
}
})
b.Run("UnsafeStringToSlice2", func(b *testing.B) {
for i := 0; i < b.N; i++ {
bs = UnsafeStringToSlice2(a)
}
})
_ = bs
}
func UnsafeStringToSlice(s string) (b []byte) {
p := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data)
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b))
hdr.Data = uintptr(p)
hdr.Cap = len(s)
hdr.Len = len(s)
return b
}
func UnsafeStringToSlice2(s string) []byte {
return *(*[]byte)(unsafe.Pointer(
&struct {
string
int
}{s, len(s)},
))
}
@dxasu 可以提个 PR 优化下这块,看了下,就是少了几个 MOVQ 指令
这比官方最新提供的解决方案还好吗?
func strToBytes(str string) []byte {
return unsafe.Slice(unsafe.StringData(str), len(str))
}
func btsToString(bts []byte) (str string) {
return unsafe.String(unsafe.SliceData(bts), len(bts))
}
官方的api暂时有版本限制,在最低go版本提升至1.20之前,暂时仍使用替代方案
我c,这都 2年了,还有没跟进版本的,滴滴k8s 版本过旧前车之鉴
https://github.com/cloudwego/gopkg/tree/main/unsafex