Skip to content

Commit

Permalink
Merge pull request globalsign#4 from cezarsa/v2-unstable
Browse files Browse the repository at this point in the history
Pool byte slices
  • Loading branch information
domodwyer committed Mar 29, 2017
2 parents 850f9b4 + 9810e05 commit 1588dc2
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 4 deletions.
9 changes: 8 additions & 1 deletion bson/bson.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,15 @@ func handleErr(err *error) {
// }
//
func Marshal(in interface{}) (out []byte, err error) {
return MarshalBuffer(in, make([]byte, 0, initialBufferSize))
}

// MarshalBuffer behaves the same way as Marshal, except that instead of
// allocating a new byte slice it tries to use the received byte slice and
// only allocates more memory if necessary to fit the marshaled value.
func MarshalBuffer(in interface{}, buf []byte) (out []byte, err error) {
defer handleErr(&err)
e := &encoder{make([]byte, 0, initialBufferSize)}
e := &encoder{buf}
e.addDoc(reflect.ValueOf(in))
return e.out, nil
}
Expand Down
7 changes: 7 additions & 0 deletions bson/bson_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,13 @@ func (s *S) TestUnmarshalNonNilInterface(c *C) {
c.Assert(m, DeepEquals, bson.M{"a": 1})
}

func (s *S) TestMarshalBuffer(c *C) {
buf := make([]byte, 0, 256)
data, err := bson.MarshalBuffer(bson.M{"a": 1}, buf)
c.Assert(err, IsNil)
c.Assert(data, DeepEquals, buf[:len(data)])
}

// --------------------------------------------------------------------------
// Some one way marshaling operations which would unmarshal differently.

Expand Down
44 changes: 44 additions & 0 deletions session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"sort"
"strconv"
"strings"
"testing"
"time"

mgo "github.com/domodwyer/mgo"
Expand Down Expand Up @@ -4425,3 +4426,46 @@ func (s *S) BenchmarkFindIterRaw(c *C) {
c.Assert(iter.Err(), IsNil)
c.Assert(i, Equals, c.N)
}

func BenchmarkInsertSingle(b *testing.B) {
session, err := mgo.Dial("localhost:40001")
if err != nil {
b.Fatal(err)
}
defer session.Close()

doc := bson.D{
{"A", strings.Repeat("*", 256)},
}
coll := session.DB("mydb").C("benchmarkcoll")
b.ResetTimer()
for i := 0; i < b.N; i++ {
err := coll.Insert(doc)
if err != nil {
b.Fatal(err)
}
}
}

func BenchmarkInsertMultiple(b *testing.B) {
session, err := mgo.Dial("localhost:40001")
if err != nil {
b.Fatal(err)
}
defer session.Close()

docs := make([]interface{}, 100)
for i := range docs {
docs[i] = bson.D{
{"A", strings.Repeat("*", 256)},
}
}
coll := session.DB("mydb").C("benchmarkcoll")
b.ResetTimer()
for i := 0; i < b.N; i++ {
err := coll.Insert(docs...)
if err != nil {
b.Fatal(err)
}
}
}
15 changes: 12 additions & 3 deletions socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,13 +375,22 @@ func (socket *mongoSocket) SimpleQuery(op *queryOp) (data []byte, err error) {
return data, err
}

var bytesBufferPool = sync.Pool{
New: func() interface{} {
return make([]byte, 0, 256)
},
}

func (socket *mongoSocket) Query(ops ...interface{}) (err error) {

if lops := socket.flushLogout(); len(lops) > 0 {
ops = append(lops, ops...)
}

buf := make([]byte, 0, 256)
buf := bytesBufferPool.Get().([]byte)
defer func() {
bytesBufferPool.Put(buf[:0])
}()

// Serialize operations synchronously to avoid interrupting
// other goroutines while we can't really be sending data.
Expand Down Expand Up @@ -677,11 +686,11 @@ func addBSON(b []byte, doc interface{}) ([]byte, error) {
if doc == nil {
return append(b, 5, 0, 0, 0, 0), nil
}
data, err := bson.Marshal(doc)
data, err := bson.MarshalBuffer(doc, b)
if err != nil {
return b, err
}
return append(b, data...), nil
return data, nil
}

func setInt32(b []byte, pos int, i int32) {
Expand Down

0 comments on commit 1588dc2

Please sign in to comment.