From 2c87abcb287f4459888941ae2633edcd8eb5b79d Mon Sep 17 00:00:00 2001 From: Kirill Korotaev Date: Sat, 7 Mar 2020 20:40:49 +0700 Subject: [PATCH] base64: avoid compliler boundary checks in the hot loop Unfortunately compiler is not capable to realise that boundary checks are not necessary on each src[si+N] access. Selection of sub-slice helps. benchmark old MB/s new MB/s speedup BenchmarkEncodeToString-8 598.08 595.89 1.00x BenchmarkDecodeString/2-8 96.32 98.97 1.03x BenchmarkDecodeString/4-8 174.19 180.41 1.04x BenchmarkDecodeString/8-8 215.03 225.91 1.05x BenchmarkDecodeString/64-8 496.53 548.24 1.10x BenchmarkDecodeString/8192-8 778.83 916.62 1.18x --- src/encoding/base64/base64.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/encoding/base64/base64.go b/src/encoding/base64/base64.go index 690d3ce0421..0c33f8e5f84 100644 --- a/src/encoding/base64/base64.go +++ b/src/encoding/base64/base64.go @@ -480,15 +480,16 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err error) { si := 0 for strconv.IntSize >= 64 && len(src)-si >= 8 && len(dst)-n >= 8 { + src2 := src[si : si+8] if dn, ok := assemble64( - enc.decodeMap[src[si+0]], - enc.decodeMap[src[si+1]], - enc.decodeMap[src[si+2]], - enc.decodeMap[src[si+3]], - enc.decodeMap[src[si+4]], - enc.decodeMap[src[si+5]], - enc.decodeMap[src[si+6]], - enc.decodeMap[src[si+7]], + enc.decodeMap[src2[0]], + enc.decodeMap[src2[1]], + enc.decodeMap[src2[2]], + enc.decodeMap[src2[3]], + enc.decodeMap[src2[4]], + enc.decodeMap[src2[5]], + enc.decodeMap[src2[6]], + enc.decodeMap[src2[7]], ); ok { binary.BigEndian.PutUint64(dst[n:], dn) n += 6 @@ -504,11 +505,12 @@ func (enc *Encoding) Decode(dst, src []byte) (n int, err error) { } for len(src)-si >= 4 && len(dst)-n >= 4 { + src2 := src[si : si+4] if dn, ok := assemble32( - enc.decodeMap[src[si+0]], - enc.decodeMap[src[si+1]], - enc.decodeMap[src[si+2]], - enc.decodeMap[src[si+3]], + enc.decodeMap[src2[0]], + enc.decodeMap[src2[1]], + enc.decodeMap[src2[2]], + enc.decodeMap[src2[3]], ); ok { binary.BigEndian.PutUint32(dst[n:], dn) n += 3