From 21ff6704bc8efa72abe191263aae938f3c867480 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Sun, 19 Feb 2023 17:11:46 -0800 Subject: encoding/json: use append for Compact and Indent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is part of the effort to reduce direct reliance on bytes.Buffer so that we can use a buffer with better pooling characteristics. Avoid direct use of bytes.Buffer in Compact and Indent and instead modify the logic to rely only on append. This avoids reliance on the bytes.Buffer.Truncate method, which makes switching to a custom buffer implementation easier. Performance: name old time/op new time/op delta EncodeMarshaler 25.5ns ± 8% 25.7ns ± 9% ~ (p=0.724 n=10+10) name old alloc/op new alloc/op delta EncodeMarshaler 4.00B ± 0% 4.00B ± 0% ~ (all equal) name old allocs/op new allocs/op delta EncodeMarshaler 1.00 ± 0% 1.00 ± 0% ~ (all equal) Updates #27735 Change-Id: I8cded03fab7651d43b5a238ee721f3472530868e Reviewed-on: https://go-review.googlesource.com/c/go/+/469555 Run-TryBot: Joseph Tsai Reviewed-by: Daniel Martí TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Auto-Submit: Joseph Tsai Reviewed-by: Bryan Mills --- src/encoding/json/encode.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src/encoding/json/encode.go') diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go index 9d59b0ff2b..d2f752a4f8 100644 --- a/src/encoding/json/encode.go +++ b/src/encoding/json/encode.go @@ -175,12 +175,12 @@ func MarshalIndent(v any, prefix, indent string) ([]byte, error) { if err != nil { return nil, err } - var buf bytes.Buffer - err = Indent(&buf, b, prefix, indent) + b2 := make([]byte, 0, indentGrowthFactor*len(b)) + b2, err = appendIndent(b2, b, prefix, indent) if err != nil { return nil, err } - return buf.Bytes(), nil + return b2, nil } // HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029 @@ -476,8 +476,10 @@ func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) { } b, err := m.MarshalJSON() if err == nil { - // copy JSON into buffer, checking validity. - err = compact(&e.Buffer, b, opts.escapeHTML) + e.Grow(len(b)) + out := availableBuffer(&e.Buffer) + out, err = appendCompact(out, b, opts.escapeHTML) + e.Buffer.Write(out) } if err != nil { e.error(&MarshalerError{v.Type(), err, "MarshalJSON"}) @@ -493,8 +495,10 @@ func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) { m := va.Interface().(Marshaler) b, err := m.MarshalJSON() if err == nil { - // copy JSON into buffer, checking validity. - err = compact(&e.Buffer, b, opts.escapeHTML) + e.Grow(len(b)) + out := availableBuffer(&e.Buffer) + out, err = appendCompact(out, b, opts.escapeHTML) + e.Buffer.Write(out) } if err != nil { e.error(&MarshalerError{v.Type(), err, "MarshalJSON"}) -- cgit v1.3