From: Tim Cooper Date: Wed, 6 Jun 2018 00:05:11 +0000 (-0300) Subject: encoding/hex: pre-allocate Dump buffer X-Git-Tag: go1.12beta1~1404 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=352583ff774d33539aeef4a3ce471406880b586d;p=gostls13.git encoding/hex: pre-allocate Dump buffer name old time/op new time/op delta Dump/256-4 7.76µs ± 2% 5.82µs ± 2% -24.91% (p=0.008 n=5+5) Dump/1024-4 28.4µs ± 2% 22.6µs ± 3% -20.58% (p=0.008 n=5+5) Dump/4096-4 112µs ± 2% 88µs ± 0% -20.80% (p=0.016 n=5+4) Dump/16384-4 444µs ± 3% 361µs ± 7% -18.73% (p=0.008 n=5+5) name old alloc/op new alloc/op delta Dump/256-4 4.00kB ± 0% 1.39kB ± 0% -65.20% (p=0.008 n=5+5) Dump/1024-4 16.2kB ± 0% 5.5kB ± 0% -66.04% (p=0.008 n=5+5) Dump/4096-4 63.9kB ± 0% 20.6kB ± 0% -67.78% (p=0.008 n=5+5) Dump/16384-4 265kB ± 0% 82kB ± 0% -69.00% (p=0.008 n=5+5) name old allocs/op new allocs/op delta Dump/256-4 7.00 ± 0% 3.00 ± 0% -57.14% (p=0.008 n=5+5) Dump/1024-4 9.00 ± 0% 3.00 ± 0% -66.67% (p=0.008 n=5+5) Dump/4096-4 11.0 ± 0% 3.0 ± 0% -72.73% (p=0.008 n=5+5) Dump/16384-4 13.0 ± 0% 3.0 ± 0% -76.92% (p=0.008 n=5+5) Change-Id: I0a0d6de315b979142b05e333880da8a5e52b12ef Reviewed-on: https://go-review.googlesource.com/116495 Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- diff --git a/src/encoding/hex/hex.go b/src/encoding/hex/hex.go index aee5aecb1a..2bb2b57df9 100644 --- a/src/encoding/hex/hex.go +++ b/src/encoding/hex/hex.go @@ -6,10 +6,10 @@ package hex import ( - "bytes" "errors" "fmt" "io" + "strings" ) const hextable = "0123456789abcdef" @@ -116,7 +116,16 @@ func DecodeString(s string) ([]byte, error) { // Dump returns a string that contains a hex dump of the given data. The format // of the hex dump matches the output of `hexdump -C` on the command line. func Dump(data []byte) string { - var buf bytes.Buffer + if len(data) == 0 { + return "" + } + + var buf strings.Builder + // Dumper will write 79 bytes per complete 16 byte chunk, and at least + // 64 bytes for whatever remains. Round the allocation up, since only a + // maximum of 15 bytes will be wasted. + buf.Grow((1 + ((len(data) - 1) / 16)) * 79) + dumper := Dumper(&buf) dumper.Write(data) dumper.Close() diff --git a/src/encoding/hex/hex_test.go b/src/encoding/hex/hex_test.go index 6ba054ef9a..e9f4b3a53a 100644 --- a/src/encoding/hex/hex_test.go +++ b/src/encoding/hex/hex_test.go @@ -248,3 +248,16 @@ func BenchmarkEncode(b *testing.B) { }) } } + +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) + sink = make([]byte, 2*size) + + b.Run(fmt.Sprintf("%v", size), func(b *testing.B) { + for i := 0; i < b.N; i++ { + Dump(src) + } + }) + } +}