diff --git a/encode.go b/encode.go index 0905c44..48791ae 100644 --- a/encode.go +++ b/encode.go @@ -98,6 +98,12 @@ func NewEncoder(w io.Writer) *Encoder { return enc } +func newEncoder() *Encoder { + enc := encPool.Get().(*Encoder) + enc.reset() + return enc +} + // Encode writes the JSON encoding of v to the stream, followed by a newline character. // // See the documentation for Marshal for details about the conversion of Go values to JSON. @@ -172,11 +178,21 @@ func (e *Encoder) encodeForMarshal(header *interfaceHeader, isNil bool) ([]byte, e.buf = buf if e.enabledIndent { - copied := make([]byte, len(buf)-2) + // this line's description is the below. + buf = buf[:len(buf)-2] + + copied := make([]byte, len(buf)) copy(copied, buf) return copied, nil } - copied := make([]byte, len(buf)-1) + + // this line exists to escape call of `runtime.makeslicecopy` . + // if use `make([]byte, len(buf)-1)` and `copy(copied, buf)`, + // dst buffer size and src buffer size are differrent. + // in this case, compiler uses `runtime.makeslicecopy`, but it is slow. + buf = buf[:len(buf)-1] + + copied := make([]byte, len(buf)) copy(copied, buf) return copied, nil } diff --git a/json.go b/json.go index 4f02347..47b09fc 100644 --- a/json.go +++ b/json.go @@ -160,8 +160,7 @@ func Marshal(v interface{}) ([]byte, error) { // MarshalNoEscape func MarshalNoEscape(v interface{}) ([]byte, error) { - var b *bytes.Buffer - enc := NewEncoder(b) + enc := newEncoder() header := (*interfaceHeader)(unsafe.Pointer(&v)) bytes, err := enc.encodeForMarshal(header, v == nil) if err != nil { @@ -174,8 +173,7 @@ func MarshalNoEscape(v interface{}) ([]byte, error) { // MarshalWithOption returns the JSON encoding of v with EncodeOption. func MarshalWithOption(v interface{}, opts ...EncodeOption) ([]byte, error) { - var b *bytes.Buffer - enc := NewEncoder(b) + enc := newEncoder() for _, opt := range opts { if err := opt(enc); err != nil { return nil, err