Merge pull request #100 from goccy/feature/optimize-encoder

Optimize copy of byte slice for encoder
This commit is contained in:
Masaaki Goshima 2021-01-27 12:11:18 +09:00 committed by GitHub
commit 94dcae2d48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 6 deletions

View File

@ -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
}

View File

@ -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