Commit 7eb7f8f5 authored by Michael Schurter's avatar Michael Schurter Committed by Brad Fitzpatrick

encoding/json: reduce allocations by Decoder for \uXXXX

Manually convert hex escape sequence to rune instead of calling
strconv.ParseUint.

This inlines the unhex func from docs (and many other packages).

name              old time/op    new time/op    delta
UnicodeDecoder-4     468ns ± 1%     402ns ± 1%  -14.26%  (p=0.000
n=10+10)

name              old speed      new speed      delta
UnicodeDecoder-4  29.9MB/s ± 1%  34.8MB/s ± 1%  +16.59%  (p=0.000
n=10+10)

name              old alloc/op   new alloc/op   delta
UnicodeDecoder-4     44.0B ± 0%     36.0B ± 0%  -18.18%  (p=0.000
n=10+10)

name              old allocs/op  new allocs/op  delta
UnicodeDecoder-4      4.00 ± 0%      2.00 ± 0%  -50.00%  (p=0.000
n=10+10)

Fixes #20567

Change-Id: If350978d5bb98ff517485752184d02249f5d1f3a
Reviewed-on: https://go-review.googlesource.com/44738
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 71aee2a1
......@@ -133,6 +133,21 @@ func BenchmarkCodeDecoder(b *testing.B) {
b.SetBytes(int64(len(codeJSON)))
}
func BenchmarkUnicodeDecoder(b *testing.B) {
j := []byte(`"\uD83D\uDE01"`)
b.SetBytes(int64(len(j)))
r := bytes.NewReader(j)
dec := NewDecoder(r)
var out string
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := dec.Decode(&out); err != nil {
b.Fatal("Decode:", err)
}
r.Seek(0, 0)
}
}
func BenchmarkDecoderStream(b *testing.B) {
b.StopTimer()
var buf bytes.Buffer
......
......@@ -1148,11 +1148,21 @@ func getu4(s []byte) rune {
if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
return -1
}
r, err := strconv.ParseUint(string(s[2:6]), 16, 64)
if err != nil {
return -1
var r rune
for _, c := range s[2:6] {
switch {
case '0' <= c && c <= '9':
c = c - '0'
case 'a' <= c && c <= 'f':
c = c - 'a' + 10
case 'A' <= c && c <= 'F':
c = c - 'A' + 10
default:
return -1
}
r = r*16 + rune(c)
}
return rune(r)
return r
}
// unquote converts a quoted JSON string literal s into an actual string t.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment