Skip to content

Commit

Permalink
Merge pull request #93 from francoispqt/update/optimize-alloc-marshal
Browse files Browse the repository at this point in the history
create new buffer before releasing only when using marshal syntax
  • Loading branch information
francoispqt committed Dec 20, 2018
2 parents 73600a9 + 1a0bd33 commit f2cc13a
Show file tree
Hide file tree
Showing 12 changed files with 66 additions and 22 deletions.
21 changes: 17 additions & 4 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -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)
}

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -133,8 +148,6 @@ func marshal(v interface{}, any bool) ([]byte, error) {
return nil, InvalidMarshalError(fmt.Sprintf(invalidMarshalErrorMsg, vt))
}
}()

enc.Release()
return buf, err
}

Expand Down
2 changes: 1 addition & 1 deletion encode_bool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestEncoderBoolErrors(t *testing.T) {
t.Run("pool-error", func(t *testing.T) {
builder := &strings.Builder{}
enc := BorrowEncoder(builder)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err shouldnt be nil")
Expand Down
2 changes: 1 addition & 1 deletion encode_embedded_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func TestEncodingEmbeddedJSON(t *testing.T) {
t.Run("pool-error", func(t *testing.T) {
v := EmbeddedJSON([]byte(`"test"`))
enc := BorrowEncoder(nil)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err shouldnt be nil")
Expand Down
2 changes: 1 addition & 1 deletion encode_interface_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func TestEncoderInterfaceEncodeAPI(t *testing.T) {
v := ""
w := TestWriterError("")
enc := BorrowEncoder(w)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err should not be nil")
Expand Down
10 changes: 5 additions & 5 deletions encode_number_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func TestEncoderNumberEncodeAPIErrors(t *testing.T) {
t.Run("encode-int-pool-error", func(t *testing.T) {
builder := &strings.Builder{}
enc := NewEncoder(builder)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err should not be nil")
Expand All @@ -92,7 +92,7 @@ func TestEncoderNumberEncodeAPIErrors(t *testing.T) {
t.Run("encode-int64-pool-error", func(t *testing.T) {
builder := &strings.Builder{}
enc := NewEncoder(builder)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err should not be nil")
Expand All @@ -112,7 +112,7 @@ func TestEncoderNumberEncodeAPIErrors(t *testing.T) {
t.Run("encode-uint64-pool-error", func(t *testing.T) {
builder := &strings.Builder{}
enc := NewEncoder(builder)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err should not be nil")
Expand All @@ -132,7 +132,7 @@ func TestEncoderNumberEncodeAPIErrors(t *testing.T) {
t.Run("encode-float64-pool-error", func(t *testing.T) {
builder := &strings.Builder{}
enc := NewEncoder(builder)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err should not be nil")
Expand All @@ -151,7 +151,7 @@ func TestEncoderNumberEncodeAPIErrors(t *testing.T) {
t.Run("encode-float32-pool-error", func(t *testing.T) {
builder := &strings.Builder{}
enc := NewEncoder(builder)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err should not be nil")
Expand Down
2 changes: 1 addition & 1 deletion encode_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions encode_object_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ func TestEncoderObjectEncodeAPIError(t *testing.T) {
t.Run("pool-error", func(t *testing.T) {
v := &TestEncoding{}
enc := BorrowEncoder(nil)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err shouldnt be nil")
Expand Down Expand Up @@ -608,7 +608,7 @@ func TestEncodeObjectWithKeys(t *testing.T) {
t.Run("pool-error", func(t *testing.T) {
v := &TestEncoding{}
enc := BorrowEncoder(nil)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err shouldnt be nil")
Expand Down
2 changes: 1 addition & 1 deletion encode_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
31 changes: 31 additions & 0 deletions encode_pool_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
8 changes: 4 additions & 4 deletions encode_sqlnull_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func TestEncoceSQLNullString(t *testing.T) {
func(t *testing.T) {
builder := &strings.Builder{}
enc := NewEncoder(builder)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err should not be nil")
Expand Down Expand Up @@ -329,7 +329,7 @@ func TestEncoceSQLNullInt64(t *testing.T) {
func(t *testing.T) {
builder := &strings.Builder{}
enc := NewEncoder(builder)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err should not be nil")
Expand Down Expand Up @@ -606,7 +606,7 @@ func TestEncoceSQLNullFloat64(t *testing.T) {
func(t *testing.T) {
builder := &strings.Builder{}
enc := NewEncoder(builder)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err should not be nil")
Expand Down Expand Up @@ -884,7 +884,7 @@ func TestEncoceSQLNullBool(t *testing.T) {
func(t *testing.T) {
builder := &strings.Builder{}
enc := NewEncoder(builder)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err should not be nil")
Expand Down
2 changes: 1 addition & 1 deletion encode_string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func TestEncoderStringEncodeAPIErrors(t *testing.T) {
t.Run("pool-error", func(t *testing.T) {
v := ""
enc := BorrowEncoder(nil)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err shouldnt be nil")
Expand Down
2 changes: 1 addition & 1 deletion encode_time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestEncodeTime(t *testing.T) {
t.Run("encode-time-pool-error", func(t *testing.T) {
builder := &strings.Builder{}
enc := NewEncoder(builder)
enc.Release()
enc.isPooled = 1
defer func() {
err := recover()
assert.NotNil(t, err, "err should not be nil")
Expand Down

0 comments on commit f2cc13a

Please sign in to comment.