1
0
mirror of https://github.com/golang/go synced 2024-11-18 18:04:46 -07:00

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
This commit is contained in:
Kirill Korotaev 2020-03-07 20:40:49 +07:00
parent ae3f98c51b
commit 2c87abcb28

View File

@ -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