mirror of https://github.com/golang/go.git
encoding/base64, encoding/base32: make Encode faster
Storing temporary values to a slice is slower than storing them to local variables of type byte. benchmark old MB/s new MB/s speedup BenchmarkEncodeToStringBase32 102.21 156.66 1.53x BenchmarkEncodeToStringBase64 124.25 177.91 1.43x LGTM=crawshaw R=golang-codereviews, crawshaw, bradfitz, dave CC=golang-codereviews https://golang.org/cl/109820045
This commit is contained in:
parent
0e92b538a9
commit
2fbfe55e63
|
|
@ -73,45 +73,43 @@ func (enc *Encoding) Encode(dst, src []byte) {
|
|||
}
|
||||
|
||||
for len(src) > 0 {
|
||||
dst[0] = 0
|
||||
dst[1] = 0
|
||||
dst[2] = 0
|
||||
dst[3] = 0
|
||||
dst[4] = 0
|
||||
dst[5] = 0
|
||||
dst[6] = 0
|
||||
dst[7] = 0
|
||||
var b0, b1, b2, b3, b4, b5, b6, b7 byte
|
||||
|
||||
// Unpack 8x 5-bit source blocks into a 5 byte
|
||||
// destination quantum
|
||||
switch len(src) {
|
||||
default:
|
||||
dst[7] |= src[4] & 0x1F
|
||||
dst[6] |= src[4] >> 5
|
||||
b7 |= src[4] & 0x1F
|
||||
b6 |= src[4] >> 5
|
||||
fallthrough
|
||||
case 4:
|
||||
dst[6] |= (src[3] << 3) & 0x1F
|
||||
dst[5] |= (src[3] >> 2) & 0x1F
|
||||
dst[4] |= src[3] >> 7
|
||||
b6 |= (src[3] << 3) & 0x1F
|
||||
b5 |= (src[3] >> 2) & 0x1F
|
||||
b4 |= src[3] >> 7
|
||||
fallthrough
|
||||
case 3:
|
||||
dst[4] |= (src[2] << 1) & 0x1F
|
||||
dst[3] |= (src[2] >> 4) & 0x1F
|
||||
b4 |= (src[2] << 1) & 0x1F
|
||||
b3 |= (src[2] >> 4) & 0x1F
|
||||
fallthrough
|
||||
case 2:
|
||||
dst[3] |= (src[1] << 4) & 0x1F
|
||||
dst[2] |= (src[1] >> 1) & 0x1F
|
||||
dst[1] |= (src[1] >> 6) & 0x1F
|
||||
b3 |= (src[1] << 4) & 0x1F
|
||||
b2 |= (src[1] >> 1) & 0x1F
|
||||
b1 |= (src[1] >> 6) & 0x1F
|
||||
fallthrough
|
||||
case 1:
|
||||
dst[1] |= (src[0] << 2) & 0x1F
|
||||
dst[0] |= src[0] >> 3
|
||||
b1 |= (src[0] << 2) & 0x1F
|
||||
b0 |= src[0] >> 3
|
||||
}
|
||||
|
||||
// Encode 5-bit blocks using the base32 alphabet
|
||||
for j := 0; j < 8; j++ {
|
||||
dst[j] = enc.encode[dst[j]]
|
||||
}
|
||||
dst[0] = enc.encode[b0]
|
||||
dst[1] = enc.encode[b1]
|
||||
dst[2] = enc.encode[b2]
|
||||
dst[3] = enc.encode[b3]
|
||||
dst[4] = enc.encode[b4]
|
||||
dst[5] = enc.encode[b5]
|
||||
dst[6] = enc.encode[b6]
|
||||
dst[7] = enc.encode[b7]
|
||||
|
||||
// Pad the final quantum
|
||||
if len(src) < 5 {
|
||||
|
|
|
|||
|
|
@ -284,3 +284,19 @@ LNEBUWIIDFON2CA3DBMJXXE5LNFY==
|
|||
t.Error("Decoded results not equal")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodeToString(b *testing.B) {
|
||||
data := make([]byte, 8192)
|
||||
b.SetBytes(int64(len(data)))
|
||||
for i := 0; i < b.N; i++ {
|
||||
StdEncoding.EncodeToString(data)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDecodeString(b *testing.B) {
|
||||
data := StdEncoding.EncodeToString(make([]byte, 8192))
|
||||
b.SetBytes(int64(len(data)))
|
||||
for i := 0; i < b.N; i++ {
|
||||
StdEncoding.DecodeString(data)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,31 +74,29 @@ func (enc *Encoding) Encode(dst, src []byte) {
|
|||
}
|
||||
|
||||
for len(src) > 0 {
|
||||
dst[0] = 0
|
||||
dst[1] = 0
|
||||
dst[2] = 0
|
||||
dst[3] = 0
|
||||
var b0, b1, b2, b3 byte
|
||||
|
||||
// Unpack 4x 6-bit source blocks into a 4 byte
|
||||
// destination quantum
|
||||
switch len(src) {
|
||||
default:
|
||||
dst[3] |= src[2] & 0x3F
|
||||
dst[2] |= src[2] >> 6
|
||||
b3 |= src[2] & 0x3F
|
||||
b2 |= src[2] >> 6
|
||||
fallthrough
|
||||
case 2:
|
||||
dst[2] |= (src[1] << 2) & 0x3F
|
||||
dst[1] |= src[1] >> 4
|
||||
b2 |= (src[1] << 2) & 0x3F
|
||||
b1 |= src[1] >> 4
|
||||
fallthrough
|
||||
case 1:
|
||||
dst[1] |= (src[0] << 4) & 0x3F
|
||||
dst[0] |= src[0] >> 2
|
||||
b1 |= (src[0] << 4) & 0x3F
|
||||
b0 |= src[0] >> 2
|
||||
}
|
||||
|
||||
// Encode 6-bit blocks using the base64 alphabet
|
||||
for j := 0; j < 4; j++ {
|
||||
dst[j] = enc.encode[dst[j]]
|
||||
}
|
||||
dst[0] = enc.encode[b0]
|
||||
dst[1] = enc.encode[b1]
|
||||
dst[2] = enc.encode[b2]
|
||||
dst[3] = enc.encode[b3]
|
||||
|
||||
// Pad the final quantum
|
||||
if len(src) < 3 {
|
||||
|
|
|
|||
|
|
@ -343,6 +343,14 @@ func TestDecoderIssue7733(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func BenchmarkEncodeToString(b *testing.B) {
|
||||
data := make([]byte, 8192)
|
||||
b.SetBytes(int64(len(data)))
|
||||
for i := 0; i < b.N; i++ {
|
||||
StdEncoding.EncodeToString(data)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDecodeString(b *testing.B) {
|
||||
data := StdEncoding.EncodeToString(make([]byte, 8192))
|
||||
b.SetBytes(int64(len(data)))
|
||||
|
|
|
|||
Loading…
Reference in New Issue