Reduce allocations when reusing a Builder.

Add the function `Reset` to the Builder, which facilitates reuse of the
underlying byte slice.
This commit is contained in:
rw 2015-04-02 19:33:00 -07:00
parent ace7fa8094
commit d756efbf76
3 changed files with 29 additions and 8 deletions

View File

@ -31,6 +31,15 @@ func NewBuilder(initialSize int) *Builder {
return b
}
// Reset truncates the underlying Builder buffer, facilitating alloc-free
// reuse of a Builder.
func (b *Builder) Reset() {
b.Bytes = b.Bytes[:0]
b.head = UOffsetT(0)
b.minalign = 1
b.vtables = b.vtables[:0]
}
// StartObject initializes bookkeeping for writing a new object.
func (b *Builder) StartObject(numfields int) {
b.notNested()
@ -155,13 +164,23 @@ func (b *Builder) growByteBuffer() {
if (int64(len(b.Bytes)) & int64(0xC0000000)) != 0 {
panic("cannot grow buffer beyond 2 gigabytes")
}
newSize := len(b.Bytes) * 2
if newSize == 0 {
newSize = 1
newLen := len(b.Bytes) * 2
if newLen == 0 {
newLen = 1
}
if cap(b.Bytes) >= newLen {
b.Bytes = b.Bytes[:newLen]
} else {
extension := make([]byte, newLen-len(b.Bytes))
b.Bytes = append(b.Bytes, extension...)
}
middle := newLen / 2
copy(b.Bytes[middle:], b.Bytes[:middle])
for i := 0 ; i < middle; i++ {
b.Bytes[i] = 0
}
bytes2 := make([]byte, newSize)
copy(bytes2[newSize-len(b.Bytes):], b.Bytes)
b.Bytes = bytes2
}
// Head gives the start of useful data in the underlying byte buffer.

View File

@ -43,7 +43,7 @@ GOPATH=${go_path} go test flatbuffers_test \
--test.coverpkg=github.com/google/flatbuffers/go \
--cpp_data=${test_dir}/monsterdata_test.mon \
--out_data=${test_dir}/monsterdata_go_wire.mon \
--test.bench=Build \
--test.bench=. \
--test.benchtime=3s \
--fuzz=true \
--fuzz_fields=4 \

View File

@ -1254,9 +1254,11 @@ func BenchmarkBuildGold(b *testing.B) {
reuse_fred := []byte("Fred")
b.SetBytes(bytes_length)
bldr := flatbuffers.NewBuilder(512)
b.ReportAllocs()
for i := 0; i < b.N; i++ {
bldr := flatbuffers.NewBuilder(0)
bldr.Reset()
str := bldr.CreateByteString(reuse_str)
test1 := bldr.CreateByteString(reuse_test1)
test2 := bldr.CreateByteString(reuse_test2)