Map.String and expvarHandler used the %q flag with fmt.Fprintf
to escape Go strings, which does so according to the Go grammar,
which is not always compatible with JSON strings.
Rather than calling json.Marshal for every string,
which will always allocate, declare a local appendJSONQuote
function that does basic string escaping.
Also, we declare an unexported appendJSON method on every
concrete Var type so that the final JSON output can be
constructed with far fewer allocations.
The resulting logic is both more correct and also much faster.
This does not alter the whitespace style of Map.String or expvarHandler,
but may alter the representation of JSON strings.
Performance:
name old time/op new time/op delta
MapString 5.10µs ± 1% 1.56µs ± 1% -69.33% (p=0.000 n=10+9)
name old alloc/op new alloc/op delta
MapString 1.21kB ± 0% 0.66kB ± 0% -45.12% (p=0.000 n=10+10)
name old allocs/op new allocs/op delta
MapString 37.0 ± 0% 7.0 ± 0% -81.08% (p=0.000 n=10+10)
Fixes #59040
Change-Id: I46a2125f43550b91d52019e5edc003d9dd19590f
Reviewed-on: https://go-review.googlesource.com/c/go/+/476336 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>