Skip to content

Commit

Permalink
utils: add Go 1.20+ way of converting string to byte slice (#2462)
Browse files Browse the repository at this point in the history
  • Loading branch information
leonklingele authored May 15, 2023
1 parent 77c1b48 commit eced39c
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 16 deletions.
16 changes: 0 additions & 16 deletions utils/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,13 @@ import (
"unsafe"
)

const MaxStringLen = 0x7fff0000 // Maximum string length for UnsafeBytes. (decimal: 2147418112)

// UnsafeString returns a string pointer without allocation
//
//nolint:gosec // unsafe is used for better performance here
func UnsafeString(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}

// UnsafeBytes returns a byte pointer without allocation.
// String length shouldn't be more than 2147418112.
//
//nolint:gosec // unsafe is used for better performance here
func UnsafeBytes(s string) []byte {
if s == "" {
return nil
}

return (*[MaxStringLen]byte)(unsafe.Pointer(
(*reflect.StringHeader)(unsafe.Pointer(&s)).Data),
)[:len(s):len(s)]
}

// CopyString copies a string to make it immutable
func CopyString(s string) string {
return string(UnsafeBytes(s))
Expand Down
13 changes: 13 additions & 0 deletions utils/convert_s2b_new.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//go:build go1.20
// +build go1.20

package utils

import (
"unsafe"
)

// UnsafeBytes returns a byte pointer without allocation.
func UnsafeBytes(s string) []byte {
return unsafe.Slice(unsafe.StringData(s), len(s))
}
25 changes: 25 additions & 0 deletions utils/convert_s2b_old.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//go:build !go1.20
// +build !go1.20

package utils

import (
"reflect"
"unsafe"
)

const MaxStringLen = 0x7fff0000 // Maximum string length for UnsafeBytes. (decimal: 2147418112)

// UnsafeBytes returns a byte pointer without allocation.
// String length shouldn't be more than 2147418112.
//
//nolint:gosec // unsafe is used for better performance here
func UnsafeBytes(s string) []byte {
if s == "" {
return nil
}

return (*[MaxStringLen]byte)(unsafe.Pointer(
(*reflect.StringHeader)(unsafe.Pointer(&s)).Data),
)[:len(s):len(s)]
}

1 comment on commit eced39c

@ReneWerner87
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 2.

Benchmark suite Current: eced39c Previous: c7c37d9 Ratio
Benchmark_AcquireCtx 1613 ns/op 1568 B/op 5 allocs/op 616.8 ns/op 1568 B/op 5 allocs/op 2.62

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.