aboutsummaryrefslogtreecommitdiff
path: root/src/encoding
diff options
context:
space:
mode:
authorDaniel Martí <mvdan@mvdan.cc>2018-12-16 19:11:28 +0100
committerDaniel Martí <mvdan@mvdan.cc>2019-02-26 19:20:07 +0000
commite90e7a59dc1aa9cd488400d58405064943b4d3c0 (patch)
treef8047648854b3a911fa3b49ee1f2602a2a53a9e6 /src/encoding
parentda50e10c2e80e8c4f53a0bb1d20de57995abc7ca (diff)
downloadgo-e90e7a59dc1aa9cd488400d58405064943b4d3c0.tar.xz
encoding/base32: simplify and speed up decoder
First, we can lift the enc.decodeMap nil check out of the loop. Second, we can make it clear to the compiler that 'in := src[0]' doesn't need a bounds check, by making len(src)==0 a single if check that always stops the loop. This is by far the largest speed-up. Third, we can use a dst slice index instead of reslicing dst, which removes work from the loop body. While at it, we can merge the two 'switch dlen' pieces of code, which simplifies the code and doesn't affect performance. name old time/op new time/op delta DecodeString-8 80.2µs ± 0% 67.5µs ± 0% -15.81% (p=0.002 n=6+6) name old speed new speed delta DecodeString-8 163MB/s ± 0% 194MB/s ± 0% +18.78% (p=0.002 n=6+6) Change-Id: Iefeaae94c03453f8760452b1da706a77b3522718 Reviewed-on: https://go-review.googlesource.com/c/154422 Run-TryBot: Daniel Martí <mvdan@mvdan.cc> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/encoding')
-rw-r--r--src/encoding/base32/base32.go52
1 files changed, 22 insertions, 30 deletions
diff --git a/src/encoding/base32/base32.go b/src/encoding/base32/base32.go
index 3fb6caceab..e14d2d4987 100644
--- a/src/encoding/base32/base32.go
+++ b/src/encoding/base32/base32.go
@@ -284,7 +284,12 @@ func (e CorruptInputError) Error() string {
// additional data is an error. This method assumes that src has been
// stripped of all supported whitespace ('\r' and '\n').
func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
+ // Lift the nil check outside of the loop.
+ _ = enc.decodeMap
+
+ dsti := 0
olen := len(src)
+
for len(src) > 0 && !end {
// Decode quantum using the base32 alphabet
var dbuf [8]byte
@@ -292,17 +297,15 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
for j := 0; j < 8; {
- // We have reached the end and are missing padding
- if len(src) == 0 && enc.padChar != NoPadding {
- return n, false, CorruptInputError(olen - len(src) - j)
- }
-
- // We have reached the end and are not expecing any padding
- if len(src) == 0 && enc.padChar == NoPadding {
+ if len(src) == 0 {
+ if enc.padChar != NoPadding {
+ // We have reached the end and are missing padding
+ return n, false, CorruptInputError(olen - len(src) - j)
+ }
+ // We have reached the end and are not expecing any padding
dlen, end = j, true
break
}
-
in := src[0]
src = src[1:]
if in == byte(enc.padChar) && j >= 2 && len(src) < 8 {
@@ -339,37 +342,26 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
// quantum
switch dlen {
case 8:
- dst[4] = dbuf[6]<<5 | dbuf[7]
+ dst[dsti+4] = dbuf[6]<<5 | dbuf[7]
+ n++
fallthrough
case 7:
- dst[3] = dbuf[4]<<7 | dbuf[5]<<2 | dbuf[6]>>3
+ dst[dsti+3] = dbuf[4]<<7 | dbuf[5]<<2 | dbuf[6]>>3
+ n++
fallthrough
case 5:
- dst[2] = dbuf[3]<<4 | dbuf[4]>>1
+ dst[dsti+2] = dbuf[3]<<4 | dbuf[4]>>1
+ n++
fallthrough
case 4:
- dst[1] = dbuf[1]<<6 | dbuf[2]<<1 | dbuf[3]>>4
+ dst[dsti+1] = dbuf[1]<<6 | dbuf[2]<<1 | dbuf[3]>>4
+ n++
fallthrough
case 2:
- dst[0] = dbuf[0]<<3 | dbuf[1]>>2
- }
-
- if !end {
- dst = dst[5:]
- }
-
- switch dlen {
- case 2:
- n += 1
- case 4:
- n += 2
- case 5:
- n += 3
- case 7:
- n += 4
- case 8:
- n += 5
+ dst[dsti+0] = dbuf[0]<<3 | dbuf[1]>>2
+ n++
}
+ dsti += 5
}
return n, end, nil
}