Skip to content

Higher performance UnsafeStringToSlice #370

@dxasu

Description

@dxasu

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions