gojay

high performance JSON encoder/decoder with stream API for Golang
git clone git://git.lair.cx/gojay
Log | Files | Refs | README | LICENSE

commit 35a95f054c7849fae3a602407a2d33583a48624f
parent 73600a98c556ff2da24a90f556188b676eaaff31
Author: francoispqt <francois@parquet.ninja>
Date:   Thu, 20 Dec 2018 15:57:23 +0800

create new buffer before releasing only when using marshal syntax - decode syntax does not need to create a new buffer as it writes directly to the reader

Diffstat:
Mencode.go | 21+++++++++++++++++----
Mencode_object.go | 2+-
Mencode_pool.go | 2+-
Mencode_pool_test.go | 31+++++++++++++++++++++++++++++++
4 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/encode.go b/encode.go @@ -34,7 +34,12 @@ func MarshalJSONArray(v MarshalerJSONArray) ([]byte, error) { enc.writeByte('[') v.(MarshalerJSONArray).MarshalJSONArray(enc) enc.writeByte(']') - defer enc.Release() + + defer func() { + enc.buf = make([]byte, 0, 512) + enc.Release() + }() + return enc.buf, nil } @@ -61,7 +66,12 @@ func MarshalJSONArray(v MarshalerJSONArray) ([]byte, error) { func MarshalJSONObject(v MarshalerJSONObject) ([]byte, error) { enc := BorrowEncoder(nil) enc.grow(512) - defer enc.Release() + + defer func() { + enc.buf = make([]byte, 0, 512) + enc.Release() + }() + return enc.encodeObject(v) } @@ -91,6 +101,11 @@ func marshal(v interface{}, any bool) ([]byte, error) { err error ) + defer func() { + enc.buf = make([]byte, 0, 512) + enc.Release() + }() + buf, err = func() ([]byte, error) { switch vt := v.(type) { case MarshalerJSONObject: @@ -133,8 +148,6 @@ func marshal(v interface{}, any bool) ([]byte, error) { return nil, InvalidMarshalError(fmt.Sprintf(invalidMarshalErrorMsg, vt)) } }() - - enc.Release() return buf, err } diff --git a/encode_object.go b/encode_object.go @@ -44,7 +44,7 @@ func (enc *Encoder) EncodeObjectKeys(v MarshalerJSONObject, keys []string) error } func (enc *Encoder) encodeObject(v MarshalerJSONObject) ([]byte, error) { - enc.grow(500) + enc.grow(512) enc.writeByte('{') if !v.IsNil() { v.MarshalJSONObject(enc) diff --git a/encode_pool.go b/encode_pool.go @@ -35,7 +35,7 @@ func NewEncoder(w io.Writer) *Encoder { func BorrowEncoder(w io.Writer) *Encoder { enc := encPool.Get().(*Encoder) enc.w = w - enc.buf = make([]byte, 0, 512) + enc.buf = enc.buf[:0] enc.isPooled = 0 enc.err = nil enc.hasKeys = false diff --git a/encode_pool_test.go b/encode_pool_test.go @@ -1 +1,32 @@ package gojay + +import ( + "fmt" + "log" + "strconv" + "testing" + "time" +) + +func TestConcurrencyMarshal(t *testing.T) { + var f = func(num int, t *testing.T) { + for { + b, err := Marshal(num) + if err != nil { + log.Fatal(err) + } + + s := string(b) + if n, err := strconv.Atoi(s); err != nil || n != num { + t.Error(fmt.Errorf( + "caught race: %v %v", s, num, + )) + } + } + } + + for i := 0; i < 100; i++ { + go f(i, t) + } + time.Sleep(2 * time.Second) +}