]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/base64, encoding/base32: make Encode faster
authorRui Ueyama <ruiu@google.com>
Wed, 18 Jun 2014 19:05:46 +0000 (12:05 -0700)
committerRui Ueyama <ruiu@google.com>
Wed, 18 Jun 2014 19:05:46 +0000 (12:05 -0700)
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

src/pkg/encoding/base32/base32.go
src/pkg/encoding/base32/base32_test.go
src/pkg/encoding/base64/base64.go
src/pkg/encoding/base64/base64_test.go

index 7613de24d275590025e3e8fd81fb1fcd7dff2ad6..ea5c0ae27cc34dff81bae3b84ba857bb59b9217a 100644 (file)
@@ -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 {
index f56b996faafa9347467def50ad30855e251ce838..5a68f06e1c94bc12e86fb2f91035fe3c1b3d4435 100644 (file)
@@ -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)
+       }
+}
index 4f1fcad9176c9d51b2ab48220a7400c4bbc013de..f89afd2b9201023958aee19d2175ea07ef3bab52 100644 (file)
@@ -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 {
index 691edb755b647702702dd8011077626644426299..7d199bfa0893150d377b1059fde987512d1c07a4 100644 (file)
@@ -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)))