Optimize encoding engine

This commit is contained in:
Masaaki Goshima 2021-01-27 00:42:19 +09:00
parent fe1fa3915a
commit 182826fe68
2 changed files with 20 additions and 6 deletions

View File

@ -98,6 +98,12 @@ func NewEncoder(w io.Writer) *Encoder {
return enc 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. // 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. // 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 e.buf = buf
if e.enabledIndent { 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) copy(copied, buf)
return copied, nil 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) copy(copied, buf)
return copied, nil return copied, nil
} }

View File

@ -160,8 +160,7 @@ func Marshal(v interface{}) ([]byte, error) {
// MarshalNoEscape // MarshalNoEscape
func MarshalNoEscape(v interface{}) ([]byte, error) { func MarshalNoEscape(v interface{}) ([]byte, error) {
var b *bytes.Buffer enc := newEncoder()
enc := NewEncoder(b)
header := (*interfaceHeader)(unsafe.Pointer(&v)) header := (*interfaceHeader)(unsafe.Pointer(&v))
bytes, err := enc.encodeForMarshal(header, v == nil) bytes, err := enc.encodeForMarshal(header, v == nil)
if err != nil { if err != nil {
@ -174,8 +173,7 @@ func MarshalNoEscape(v interface{}) ([]byte, error) {
// MarshalWithOption returns the JSON encoding of v with EncodeOption. // MarshalWithOption returns the JSON encoding of v with EncodeOption.
func MarshalWithOption(v interface{}, opts ...EncodeOption) ([]byte, error) { func MarshalWithOption(v interface{}, opts ...EncodeOption) ([]byte, error) {
var b *bytes.Buffer enc := newEncoder()
enc := NewEncoder(b)
for _, opt := range opts { for _, opt := range opts {
if err := opt(enc); err != nil { if err := opt(enc); err != nil {
return nil, err return nil, err