mirror of
https://github.com/golang/go
synced 2024-09-15 22:20:06 +00:00
encoding/base64: optimize decodemap memory set
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: 55dce6f636
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>
This commit is contained in:
parent
0d8efa6e84
commit
e1b62efaf3
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
|
|
Loading…
Reference in a new issue