1
0
mirror of https://github.com/golang/go synced 2024-11-22 22:40:02 -07:00

encoding/json: allocate less in NewEncoder

The *Encoder is almost always garbage. It doesn't need an
encodeState inside of it (and its bytes.Buffer), since it's
only needed locally inside of Encode.

benchmark                 old ns/op    new ns/op    delta
BenchmarkEncoderEncode         2562         2553   -0.35%

benchmark                 old bytes    new bytes    delta
BenchmarkEncoderEncode          283          102  -63.96%

R=r
CC=gobot, golang-dev
https://golang.org/cl/9365044
This commit is contained in:
Brad Fitzpatrick 2013-05-14 15:50:46 -07:00
parent d73452b30f
commit f1583bb956
3 changed files with 38 additions and 4 deletions

View File

@ -227,6 +227,26 @@ type encodeState struct {
scratch [64]byte
}
// TODO(bradfitz): use a sync.Cache here
var encodeStatePool = make(chan *encodeState, 8)
func newEncodeState() *encodeState {
select {
case e := <-encodeStatePool:
e.Reset()
return e
default:
return new(encodeState)
}
}
func putEncodeState(e *encodeState) {
select {
case encodeStatePool <- e:
default:
}
}
func (e *encodeState) marshal(v interface{}) (err error) {
defer func() {
if r := recover(); r != nil {

View File

@ -156,8 +156,8 @@ func (enc *Encoder) Encode(v interface{}) error {
if enc.err != nil {
return enc.err
}
enc.e.Reset()
err := enc.e.marshal(v)
e := newEncodeState()
err := e.marshal(v)
if err != nil {
return err
}
@ -168,11 +168,12 @@ func (enc *Encoder) Encode(v interface{}) error {
// is required if the encoded value was a number,
// so that the reader knows there aren't more
// digits coming.
enc.e.WriteByte('\n')
e.WriteByte('\n')
if _, err = enc.w.Write(enc.e.Bytes()); err != nil {
if _, err = enc.w.Write(e.Bytes()); err != nil {
enc.err = err
}
putEncodeState(e)
return err
}

View File

@ -191,3 +191,16 @@ func TestBlocking(t *testing.T) {
w.Close()
}
}
func BenchmarkEncoderEncode(b *testing.B) {
b.ReportAllocs()
type T struct {
X, Y string
}
v := &T{"foo", "bar"}
for i := 0; i < b.N; i++ {
if err := NewEncoder(ioutil.Discard).Encode(v); err != nil {
b.Fatal(err)
}
}
}