]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/base64: lift nil check out of encode loop
authorDaniel Martí <mvdan@mvdan.cc>
Sun, 25 Nov 2018 14:53:24 +0000 (14:53 +0000)
committerDaniel Martí <mvdan@mvdan.cc>
Sun, 3 Mar 2019 10:33:18 +0000 (10:33 +0000)
Most of the encoding time is spent in the first Encode loop, since the
rest of the function only deals with the few remaining bytes. Any
unnecessary work done in that loop body matters tremendously.

One such unnecessary bottleneck was the use of the enc.encode table.
Since enc is a pointer receiver, and the field is first used within the
loop, the encoder must perform a nil check at every iteration.

Add a dummy use of the field before the start of the loop, to move the
nil check there. After that line, the compiler now knows that enc can't
be nil, and thus the hot loop is free of nil checks.

name              old time/op    new time/op    delta
EncodeToString-4    14.7µs ± 0%    13.7µs ± 1%  -6.53%  (p=0.000 n=10+10)

name              old speed      new speed      delta
EncodeToString-4   559MB/s ± 0%   598MB/s ± 1%  +6.99%  (p=0.000 n=10+10)

Updates #20206.

Change-Id: Icbb523a7bd9e470a8be0a448d1d78ade97ed4ff6
Reviewed-on: https://go-review.googlesource.com/c/151158
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/encoding/base64/base64.go

index 0bb37b311a0992f9d6055b54b6cc3ba727326c0f..a90e4dfa1270a276b39544dde17c590768ddf73a 100644 (file)
@@ -123,6 +123,10 @@ func (enc *Encoding) Encode(dst, src []byte) {
        if len(src) == 0 {
                return
        }
+       // enc is a pointer receiver, so the use of enc.encode within the hot
+       // loop below means a nil check at every operation. Lift that nil check
+       // outside of the loop to speed up the encoder.
+       _ = enc.encode
 
        di, si := 0, 0
        n := (len(src) / 3) * 3