]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/base64: optimize decodemap memory set
authorErikPelli <erikpellizzon1@gmail.com>
Sun, 14 Aug 2022 07:46:22 +0000 (07:46 +0000)
committerGopher Robot <gobot@golang.org>
Wed, 17 Aug 2022 03:15:44 +0000 (03:15 +0000)
The existing implementation has an execution time higher in the benchmark than this one.
This is an optimized implementation using the copy() function and a constant 256 bytes string with the values to be copied.

```
name           old time/op    new time/op    delta
NewEncoding-4     329ns ± 1%     231ns ± 1%  -29.72%  (p=0.008 n=5+5)

name           old speed      new speed      delta
NewEncoding-4   778MB/s ± 1%  1108MB/s ± 1%  +42.29%  (p=0.008 n=5+5)
```

Fixes #53211

Change-Id: I80fe62aa40623125ef81ae9164a8405eed30b71b
GitHub-Last-Rev: 55dce6f636ad29a70daa935169710c22f44ab31f
GitHub-Pull-Request: golang/go#53212
Reviewed-on: https://go-review.googlesource.com/c/go/+/410194
Reviewed-by: Keith Randall <khr@google.com>
Run-TryBot: Keith Randall <khr@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Auto-Submit: Keith Randall <khr@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
src/encoding/base32/base32.go
src/encoding/base64/base64.go
src/encoding/base64/base64_test.go

index fa6e42e26c557c516b5816899a96808a2ac9ee42..41d343aaac0fcaad798a5738dbbe0fd3264cb9d2 100644 (file)
@@ -25,8 +25,25 @@ type Encoding struct {
 }
 
 const (
-       StdPadding rune = '=' // Standard padding character
-       NoPadding  rune = -1  // No padding
+       StdPadding          rune = '=' // Standard padding character
+       NoPadding           rune = -1  // No padding
+       decodeMapInitialize      = "" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
 )
 
 const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
@@ -40,12 +57,10 @@ func NewEncoding(encoder string) *Encoding {
        }
 
        e := new(Encoding)
-       copy(e.encode[:], encoder)
        e.padChar = StdPadding
+       copy(e.encode[:], encoder)
+       copy(e.decodeMap[:], decodeMapInitialize)
 
-       for i := 0; i < len(e.decodeMap); i++ {
-               e.decodeMap[i] = 0xFF
-       }
        for i := 0; i < len(encoder); i++ {
                e.decodeMap[encoder[i]] = byte(i)
        }
index 4a3e590649ea95e62dadd92cea0006227f008a4b..0e12d90d29895a208f08b38a07b405134335602d 100644 (file)
@@ -28,8 +28,25 @@ type Encoding struct {
 }
 
 const (
-       StdPadding rune = '=' // Standard padding character
-       NoPadding  rune = -1  // No padding
+       StdPadding          rune = '=' // Standard padding character
+       NoPadding           rune = -1  // No padding
+       decodeMapInitialize      = "" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" +
+               "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
 )
 
 const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
@@ -53,10 +70,8 @@ func NewEncoding(encoder string) *Encoding {
        e := new(Encoding)
        e.padChar = StdPadding
        copy(e.encode[:], encoder)
+       copy(e.decodeMap[:], decodeMapInitialize)
 
-       for i := 0; i < len(e.decodeMap); i++ {
-               e.decodeMap[i] = 0xFF
-       }
        for i := 0; i < len(encoder); i++ {
                e.decodeMap[encoder[i]] = byte(i)
        }
index 57256a3846acbeb1eb2fa4f27bfda83b9b55fd3c..852446dd8b3f45c5de34017c9d800e0af82fbd9e 100644 (file)
@@ -504,6 +504,16 @@ func BenchmarkDecodeString(b *testing.B) {
        }
 }
 
+func BenchmarkNewEncoding(b *testing.B) {
+       b.SetBytes(int64(len(Encoding{}.decodeMap)))
+       for i := 0; i < b.N; i++ {
+               e := NewEncoding(encodeStd)
+               for _, v := range e.decodeMap {
+                       _ = v
+               }
+       }
+}
+
 func TestDecoderRaw(t *testing.T) {
        source := "AAAAAA"
        want := []byte{0, 0, 0, 0}