Skip to content

Commit 1588dc2

Browse files
authored
Merge pull request globalsign#4 from cezarsa/v2-unstable
Pool byte slices
2 parents 850f9b4 + 9810e05 commit 1588dc2

File tree

4 files changed

+71
-4
lines changed

4 files changed

+71
-4
lines changed

bson/bson.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,15 @@ func handleErr(err *error) {
508508
// }
509509
//
510510
func Marshal(in interface{}) (out []byte, err error) {
511+
return MarshalBuffer(in, make([]byte, 0, initialBufferSize))
512+
}
513+
514+
// MarshalBuffer behaves the same way as Marshal, except that instead of
515+
// allocating a new byte slice it tries to use the received byte slice and
516+
// only allocates more memory if necessary to fit the marshaled value.
517+
func MarshalBuffer(in interface{}, buf []byte) (out []byte, err error) {
511518
defer handleErr(&err)
512-
e := &encoder{make([]byte, 0, initialBufferSize)}
519+
e := &encoder{buf}
513520
e.addDoc(reflect.ValueOf(in))
514521
return e.out, nil
515522
}

bson/bson_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,13 @@ func (s *S) TestUnmarshalNonNilInterface(c *C) {
246246
c.Assert(m, DeepEquals, bson.M{"a": 1})
247247
}
248248

249+
func (s *S) TestMarshalBuffer(c *C) {
250+
buf := make([]byte, 0, 256)
251+
data, err := bson.MarshalBuffer(bson.M{"a": 1}, buf)
252+
c.Assert(err, IsNil)
253+
c.Assert(data, DeepEquals, buf[:len(data)])
254+
}
255+
249256
// --------------------------------------------------------------------------
250257
// Some one way marshaling operations which would unmarshal differently.
251258

session_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"sort"
3636
"strconv"
3737
"strings"
38+
"testing"
3839
"time"
3940

4041
mgo "github.com/domodwyer/mgo"
@@ -4425,3 +4426,46 @@ func (s *S) BenchmarkFindIterRaw(c *C) {
44254426
c.Assert(iter.Err(), IsNil)
44264427
c.Assert(i, Equals, c.N)
44274428
}
4429+
4430+
func BenchmarkInsertSingle(b *testing.B) {
4431+
session, err := mgo.Dial("localhost:40001")
4432+
if err != nil {
4433+
b.Fatal(err)
4434+
}
4435+
defer session.Close()
4436+
4437+
doc := bson.D{
4438+
{"A", strings.Repeat("*", 256)},
4439+
}
4440+
coll := session.DB("mydb").C("benchmarkcoll")
4441+
b.ResetTimer()
4442+
for i := 0; i < b.N; i++ {
4443+
err := coll.Insert(doc)
4444+
if err != nil {
4445+
b.Fatal(err)
4446+
}
4447+
}
4448+
}
4449+
4450+
func BenchmarkInsertMultiple(b *testing.B) {
4451+
session, err := mgo.Dial("localhost:40001")
4452+
if err != nil {
4453+
b.Fatal(err)
4454+
}
4455+
defer session.Close()
4456+
4457+
docs := make([]interface{}, 100)
4458+
for i := range docs {
4459+
docs[i] = bson.D{
4460+
{"A", strings.Repeat("*", 256)},
4461+
}
4462+
}
4463+
coll := session.DB("mydb").C("benchmarkcoll")
4464+
b.ResetTimer()
4465+
for i := 0; i < b.N; i++ {
4466+
err := coll.Insert(docs...)
4467+
if err != nil {
4468+
b.Fatal(err)
4469+
}
4470+
}
4471+
}

socket.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -375,13 +375,22 @@ func (socket *mongoSocket) SimpleQuery(op *queryOp) (data []byte, err error) {
375375
return data, err
376376
}
377377

378+
var bytesBufferPool = sync.Pool{
379+
New: func() interface{} {
380+
return make([]byte, 0, 256)
381+
},
382+
}
383+
378384
func (socket *mongoSocket) Query(ops ...interface{}) (err error) {
379385

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

384-
buf := make([]byte, 0, 256)
390+
buf := bytesBufferPool.Get().([]byte)
391+
defer func() {
392+
bytesBufferPool.Put(buf[:0])
393+
}()
385394

386395
// Serialize operations synchronously to avoid interrupting
387396
// other goroutines while we can't really be sending data.
@@ -677,11 +686,11 @@ func addBSON(b []byte, doc interface{}) ([]byte, error) {
677686
if doc == nil {
678687
return append(b, 5, 0, 0, 0, 0), nil
679688
}
680-
data, err := bson.Marshal(doc)
689+
data, err := bson.MarshalBuffer(doc, b)
681690
if err != nil {
682691
return b, err
683692
}
684-
return append(b, data...), nil
693+
return data, nil
685694
}
686695

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

0 commit comments

Comments
 (0)