Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Higher performance UnsafeStringToSlice #370

Open
dxasu opened this issue Nov 22, 2024 · 4 comments · May be fixed by #371
Open

Higher performance UnsafeStringToSlice #370

dxasu opened this issue Nov 22, 2024 · 4 comments · May be fixed by #371

Comments

@dxasu
Copy link
Contributor

dxasu commented Nov 22, 2024

func unsafeStringToSlice(s string) (b []byte) {

建议用如下函数替换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)},
	))
}

@joway
Copy link
Member

joway commented Nov 22, 2024

@dxasu 可以提个 PR 优化下这块,看了下,就是少了几个 MOVQ 指令
image

@dxasu dxasu linked a pull request Nov 22, 2024 that will close this issue
3 tasks
@someview
Copy link

这比官方最新提供的解决方案还好吗?

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))
}

@jayantxie
Copy link
Member

官方的api暂时有版本限制,在最低go版本提升至1.20之前,暂时仍使用替代方案

@someview
Copy link

我c,这都 2年了,还有没跟进版本的,滴滴k8s 版本过旧前车之鉴

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

4 participants