]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/hex: simplify decoder arithmetic
authorDaniel Martí <mvdan@mvdan.cc>
Sun, 25 Nov 2018 23:22:11 +0000 (23:22 +0000)
committerDaniel Martí <mvdan@mvdan.cc>
Sat, 2 Mar 2019 16:48:05 +0000 (16:48 +0000)
Remove all multiplications and divisions from the main decoding loop.

name            old time/op   new time/op   delta
Decode/256-8      323ns ± 0%    293ns ± 0%   -9.29%  (p=0.000 n=5+4)
Decode/1024-8    1.26µs ± 0%   1.14µs ± 0%   -9.48%  (p=0.000 n=6+5)
Decode/4096-8    4.99µs ± 0%   4.51µs ± 0%   -9.55%  (p=0.002 n=6+6)
Decode/16384-8   20.0µs ± 0%   18.1µs ± 0%   -9.54%  (p=0.002 n=6+6)

name            old speed     new speed     delta
Decode/256-8    791MB/s ± 0%  872MB/s ± 0%  +10.34%  (p=0.002 n=6+6)
Decode/1024-8   814MB/s ± 0%  899MB/s ± 0%  +10.48%  (p=0.004 n=6+5)
Decode/4096-8   821MB/s ± 0%  908MB/s ± 0%  +10.55%  (p=0.002 n=6+6)
Decode/16384-8  821MB/s ± 0%  908MB/s ± 0%  +10.54%  (p=0.002 n=6+6)

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

index 2bb2b57df9cd990c7568c0faee6be017f3545574..7675de9bd9c90267b1aea62289b382c31d1ef6d4 100644 (file)
@@ -55,23 +55,24 @@ func DecodedLen(x int) int { return x / 2 }
 // If the input is malformed, Decode returns the number
 // of bytes decoded before the error.
 func Decode(dst, src []byte) (int, error) {
-       var i int
-       for i = 0; i < len(src)/2; i++ {
-               a, ok := fromHexChar(src[i*2])
+       i, j := 0, 1
+       for ; j < len(src); j += 2 {
+               a, ok := fromHexChar(src[j-1])
                if !ok {
-                       return i, InvalidByteError(src[i*2])
+                       return i, InvalidByteError(src[j-1])
                }
-               b, ok := fromHexChar(src[i*2+1])
+               b, ok := fromHexChar(src[j])
                if !ok {
-                       return i, InvalidByteError(src[i*2+1])
+                       return i, InvalidByteError(src[j])
                }
                dst[i] = (a << 4) | b
+               i++
        }
        if len(src)%2 == 1 {
                // Check for invalid char before reporting bad length,
                // since the invalid char (if present) is an earlier problem.
-               if _, ok := fromHexChar(src[i*2]); !ok {
-                       return i, InvalidByteError(src[i*2])
+               if _, ok := fromHexChar(src[j-1]); !ok {
+                       return i, InvalidByteError(src[j-1])
                }
                return i, ErrLength
        }
index e9f4b3a53adefda92097e1429a478426ee04acd4..ba703cf1c1f063f3b697238f07981c93d241cb56 100644 (file)
@@ -249,6 +249,20 @@ func BenchmarkEncode(b *testing.B) {
        }
 }
 
+func BenchmarkDecode(b *testing.B) {
+       for _, size := range []int{256, 1024, 4096, 16384} {
+               src := bytes.Repeat([]byte{'2', 'b', '7', '4', '4', 'f', 'a', 'a'}, size/8)
+               sink = make([]byte, size/2)
+
+               b.Run(fmt.Sprintf("%v", size), func(b *testing.B) {
+                       b.SetBytes(int64(size))
+                       for i := 0; i < b.N; i++ {
+                               Decode(sink, src)
+                       }
+               })
+       }
+}
+
 func BenchmarkDump(b *testing.B) {
        for _, size := range []int{256, 1024, 4096, 16384} {
                src := bytes.Repeat([]byte{2, 3, 5, 7, 9, 11, 13, 17}, size/8)