Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
qingyang-hu committed Jul 4, 2024
1 parent 615c93d commit 6d76528
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 57 deletions.
10 changes: 8 additions & 2 deletions bson/default_value_encoders.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import (
"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
)

var bvwPool = NewValueWriterPool()
var bvwPool = sync.Pool{
New: func() interface{} {
return new(valueWriter)
},
}

var errInvalidValue = errors.New("cannot encode invalid element")

Expand Down Expand Up @@ -511,7 +515,9 @@ func codeWithScopeEncodeValue(ec EncodeContext, vw ValueWriter, val reflect.Valu
defer sliceWriterPool.Put(sw)
*sw = (*sw)[:0]

scopeVW := bvwPool.Get(sw)
scopeVW := bvwPool.Get().(*valueWriter)
scopeVW.reset(scopeVW.buf[:0])
scopeVW.w = sw
defer bvwPool.Put(scopeVW)

encoder, err := ec.LookupEncoder(reflect.TypeOf(cws.Scope))
Expand Down
27 changes: 23 additions & 4 deletions bson/marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,26 @@ func MarshalValue(val interface{}) (Type, []byte, error) {
// Deprecated: Using a custom registry to marshal individual BSON values will not be supported in Go
// Driver 2.0.
func MarshalValueWithRegistry(r *Registry, val interface{}) (Type, []byte, error) {
sw := sliceWriter(make([]byte, 0))
vw := bvwPool.Get(&sw).(*valueWriter)
sw := bufPool.Get().(*bytes.Buffer)
defer func() {
// Proper usage of a sync.Pool requires each entry to have approximately
// the same memory cost. To obtain this property when the stored type
// contains a variably-sized buffer, we add a hard limit on the maximum
// buffer to place back in the pool. We limit the size to 16MiB because
// that's the maximum wire message size supported by any current MongoDB
// server.
//
// Comment based on
// https://cs.opensource.google/go/go/+/refs/tags/go1.19:src/fmt/print.go;l=147
//
// Recycle byte slices that are smaller than 16MiB and at least half
// occupied.
if sw.Cap() < 16*1024*1024 && sw.Cap()/2 < sw.Len() {
bufPool.Put(sw)
}
}()
sw.Reset()
vw := NewValueWriter(sw).(*valueWriter)
vwFlusher, err := vw.WriteDocumentElement("")
if err != nil {
return 0, nil, err
Expand All @@ -107,7 +125,7 @@ func MarshalValueWithRegistry(r *Registry, val interface{}) (Type, []byte, error
enc := encPool.Get().(*Encoder)
defer encPool.Put(enc)
enc.Reset(vwFlusher)
enc.ec = EncodeContext{Registry: r}
enc.SetRegistry(r)
if err := enc.Encode(val); err != nil {
return 0, nil, err
}
Expand All @@ -118,7 +136,8 @@ func MarshalValueWithRegistry(r *Registry, val interface{}) (Type, []byte, error
if err := vw.Flush(); err != nil {
return 0, nil, err
}
return Type(sw[0]), sw[2:], nil
buf := sw.Bytes()
return Type(buf[0]), buf[2:], nil
}

// MarshalExtJSON returns the extended JSON encoding of val.
Expand Down
47 changes: 0 additions & 47 deletions bson/value_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,53 +33,6 @@ func putValueWriter(vw *valueWriter) {
}
}

// ValueWriterPool is a pool for BSON ValueWriters.
//
// Deprecated: ValueWriterPool will not be supported in Go Driver 2.0.
type ValueWriterPool struct {
pool sync.Pool
}

// NewValueWriterPool creates a new pool for ValueWriter instances that write to BSON.
//
// Deprecated: ValueWriterPool will not be supported in Go Driver 2.0.
func NewValueWriterPool() *ValueWriterPool {
return &ValueWriterPool{
pool: sync.Pool{
New: func() interface{} {
return new(valueWriter)
},
},
}
}

// Get retrieves a BSON ValueWriter from the pool and resets it to use w as the destination.
//
// Deprecated: ValueWriterPool will not be supported in Go Driver 2.0.
func (bvwp *ValueWriterPool) Get(w io.Writer) ValueWriter {
vw := bvwp.pool.Get().(*valueWriter)

// TODO: Having to call reset here with the same buffer doesn't really make sense.
vw.reset(vw.buf)
vw.buf = vw.buf[:0]
vw.w = w
return vw
}

// Put inserts a ValueWriter into the pool. If the ValueWriter is not a BSON ValueWriter, nothing
// happens and ok will be false.
//
// Deprecated: ValueWriterPool will not be supported in Go Driver 2.0.
func (bvwp *ValueWriterPool) Put(vw ValueWriter) (ok bool) {
bvw, ok := vw.(*valueWriter)
if !ok {
return false
}

bvwp.pool.Put(bvw)
return true
}

// This is here so that during testing we can change it and not require
// allocating a 4GB slice.
var maxSize = math.MaxInt32
Expand Down
5 changes: 1 addition & 4 deletions mongo/mongo.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,14 @@ func (me MarshalError) Error() string {
// }
type Pipeline []bson.D

// bvwPool is a pool of BSON value writers. BSON value writers
var bvwPool = bson.NewValueWriterPool()

// getEncoder takes a writer, BSON options, and a BSON registry and returns a properly configured
// bson.Encoder that writes to the given writer.
func getEncoder(
w io.Writer,
opts *options.BSONOptions,
reg *bson.Registry,
) (*bson.Encoder, error) {
vw := bvwPool.Get(w)
vw := bson.NewValueWriter(w)
enc := bson.NewEncoder(vw)

if opts != nil {
Expand Down

0 comments on commit 6d76528

Please sign in to comment.