From 2d41d2b734d8b15151d7dfcd6fba3ebce7646f8d Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Tue, 24 Nov 2015 13:22:34 +0200 Subject: [PATCH] Optimized AppendBytesStr - now it is 2x faster --- bytesconv.go | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/bytesconv.go b/bytesconv.go index 0e1b83c..4c2cb71 100644 --- a/bytesconv.go +++ b/bytesconv.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "math" + "reflect" "sync" "time" "unsafe" @@ -255,7 +256,7 @@ func lowercaseBytes(b []byte) { } } -// Converts byte slice to a string without memory allocation. +// unsafeBytesToStr converts byte slice to a string without memory allocation. // See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ . // // Note it may break if string and/or slice header will change @@ -264,6 +265,19 @@ func unsafeBytesToStr(b []byte) string { return *(*string)(unsafe.Pointer(&b)) } +// unsafeStrToBytes converts string to byte slice without memory allocation. +// +// The returned byte slice may be read until references to the original s exist. +func unsafeStrToBytes(s string) []byte { + sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) + bh := reflect.SliceHeader{ + Data: sh.Data, + Len: sh.Len, + Cap: sh.Len, + } + return *(*[]byte)(unsafe.Pointer(&bh)) +} + func unhex(c byte) int { if c >= '0' && c <= '9' { return int(c - '0') @@ -306,8 +320,8 @@ func EqualBytesStr(b []byte, s string) bool { // AppendBytesStr appends src to dst and returns dst // (which may be newly allocated). func AppendBytesStr(dst []byte, src string) []byte { - for i, n := 0, len(src); i < n; i++ { - dst = append(dst, src[i]) - } - return dst + // The following code is equivalent to + // return append(dst, []byte(src)...) + // but it is 1.5x faster in Go1.5. I don't know why :) + return append(dst, unsafeStrToBytes(src)...) }