diff --git a/bench_test.go b/bench_test.go index cd36ee4c..761bff91 100644 --- a/bench_test.go +++ b/bench_test.go @@ -5,7 +5,7 @@ package cbor import ( "bytes" - "io/ioutil" + "io" "reflect" "testing" ) @@ -415,6 +415,29 @@ func BenchmarkMarshalCanonical(b *testing.B) { } } +// BenchmarkNewEncoderEncode benchmarks NewEncoder() and Encode(). +func BenchmarkNewEncoderEncode(b *testing.B) { + for _, bm := range encodeBenchmarks { + for _, v := range bm.values { + name := "Go " + reflect.TypeOf(v).String() + " to CBOR " + bm.name + if reflect.TypeOf(v).Kind() == reflect.Struct { + name = "Go " + reflect.TypeOf(v).Kind().String() + " to CBOR " + bm.name + } + b.Run(name, func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + encoder := NewEncoder(io.Discard) + if err := encoder.Encode(v); err != nil { + b.Fatal("Encode:", err) + } + } + }) + } + } +} + +// BenchmarkEncode benchmarks Encode(). It reuses same Encoder to exclude NewEncoder() +// from the benchmark. func BenchmarkEncode(b *testing.B) { for _, bm := range encodeBenchmarks { for _, v := range bm.values { @@ -423,7 +446,7 @@ func BenchmarkEncode(b *testing.B) { name = "Go " + reflect.TypeOf(v).Kind().String() + " to CBOR " + bm.name } b.Run(name, func(b *testing.B) { - encoder := NewEncoder(ioutil.Discard) + encoder := NewEncoder(io.Discard) b.ResetTimer() for i := 0; i < b.N; i++ { if err := encoder.Encode(v); err != nil { @@ -437,7 +460,7 @@ func BenchmarkEncode(b *testing.B) { func BenchmarkEncodeStream(b *testing.B) { for i := 0; i < b.N; i++ { - encoder := NewEncoder(ioutil.Discard) + encoder := NewEncoder(io.Discard) for i := 0; i < rounds; i++ { for _, bm := range encodeBenchmarks { for _, v := range bm.values { diff --git a/encode.go b/encode.go index a2a26574..10255a60 100644 --- a/encode.go +++ b/encode.go @@ -577,7 +577,7 @@ func (em *encMode) Marshal(v interface{}) ([]byte, error) { // NewEncoder returns a new encoder that writes to w using em EncMode. func (em *encMode) NewEncoder(w io.Writer) *Encoder { - return &Encoder{w: w, em: em, e: getEncoderBuffer()} + return &Encoder{w: w, em: em} } type encoderBuffer struct { diff --git a/stream.go b/stream.go index c559f52d..45a3422c 100644 --- a/stream.go +++ b/stream.go @@ -130,7 +130,6 @@ func (dec *Decoder) overwriteBuf(newBuf []byte) { type Encoder struct { w io.Writer em *encMode - e *encoderBuffer indefTypes []cborType } @@ -157,11 +156,14 @@ func (enc *Encoder) Encode(v interface{}) error { } } - err := encode(enc.e, enc.em, reflect.ValueOf(v)) + buf := getEncoderBuffer() + + err := encode(buf, enc.em, reflect.ValueOf(v)) if err == nil { - _, err = enc.e.WriteTo(enc.w) + _, err = enc.w.Write(buf.Bytes()) } - enc.e.Reset() + + putEncoderBuffer(buf) return err }