Skip to content

Commit 9ecefc4

Browse files
committed
base64: don't reallocate/copy []byte <-> string
Converting []byte to string and vice versa allocates and copies the buffer, which is not really needed and has a significant performance hit. benchmark old MB/s new MB/s speedup BenchmarkEncodeToString-8 608.04 678.24 1.12x BenchmarkDecodeString/2-8 93.07 111.61 1.20x BenchmarkDecodeString/4-8 160.39 183.22 1.14x BenchmarkDecodeString/8-8 210.65 249.11 1.18x BenchmarkDecodeString/64-8 476.13 653.02 1.37x BenchmarkDecodeString/8192-8 837.51 950.17 1.13x
1 parent 9bb40ed commit 9ecefc4

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

src/encoding/base64/base64.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ package base64
88
import (
99
"encoding/binary"
1010
"io"
11+
"reflect"
1112
"strconv"
13+
"unsafe"
1214
)
1315

1416
/*
@@ -177,7 +179,8 @@ func (enc *Encoding) Encode(dst, src []byte) {
177179
func (enc *Encoding) EncodeToString(src []byte) string {
178180
buf := make([]byte, enc.EncodedLen(len(src)))
179181
enc.Encode(buf, src)
180-
return string(buf)
182+
183+
return *(*string)(unsafe.Pointer(&buf))
181184
}
182185

183186
type encoder struct {
@@ -382,7 +385,12 @@ func (enc *Encoding) decodeQuantum(dst, src []byte, si int) (nsi, n int, err err
382385
// DecodeString returns the bytes represented by the base64 string s.
383386
func (enc *Encoding) DecodeString(s string) ([]byte, error) {
384387
dbuf := make([]byte, enc.DecodedLen(len(s)))
385-
n, err := enc.Decode(dbuf, []byte(s))
388+
389+
h := (*reflect.StringHeader)(unsafe.Pointer(&s))
390+
shdr := reflect.SliceHeader{Data: h.Data, Len: h.Len, Cap: h.Len}
391+
sbuf := *(*[]byte)(unsafe.Pointer(&shdr))
392+
393+
n, err := enc.Decode(dbuf, sbuf)
386394
return dbuf[:n], err
387395
}
388396

0 commit comments

Comments
 (0)