From 6a0126340a3767cc6f4988b861f1340ce6a747ea Mon Sep 17 00:00:00 2001 From: Ben Harper Date: Sun, 8 Mar 2015 21:39:01 +0200 Subject: [PATCH] Add CreateByteVector function to Go's builder This function gets around the inefficiency of populating a [ubyte] vector byte by byte. Since ubyte vectors are probably the most commonly used type of generic byte buffer, this seems like a worthwhile thing to create a fast path for. Benchmarks show a 6x improvement in throughput on x64. There is a new test verifying the functionality of the function. Change-Id: I82e0228ae0f815dd7ea89bf168b8c1925f3ce0d7 --- go/builder.go | 12 ++++++++++++ tests/go_test.go | 22 ++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/go/builder.go b/go/builder.go index 94e7e95a6..e1b1f4308 100644 --- a/go/builder.go +++ b/go/builder.go @@ -259,6 +259,18 @@ func (b *Builder) CreateString(s string) UOffsetT { return b.EndVector(len(x)) } +// CreateByteVector writes a ubyte vector +func (b *Builder) CreateByteVector(v []byte) UOffsetT { + b.Prep(int(SizeUOffsetT), len(v)*SizeByte) + + l := UOffsetT(len(v)) + + b.head -= l + copy(b.Bytes[b.head:b.head+l], v) + + return b.EndVector(len(v)) +} + func (b *Builder) notNested() { // Check that no other objects are being built while making this // object. If not, panic: diff --git a/tests/go_test.go b/tests/go_test.go index a9496355d..03eaddfad 100644 --- a/tests/go_test.go +++ b/tests/go_test.go @@ -90,6 +90,9 @@ func TestAll(t *testing.T) { // some sanity checks: CheckDocExample(generated, off, t.Fatalf) + // Check Builder.CreateByteVector + CheckCreateByteVector(t.Fatalf) + // If the filename of the FlatBuffers file generated by the Java test // is given, check that Go code can read it, and that Go code // generates an identical buffer when used to create the example data: @@ -1080,6 +1083,25 @@ func CheckDocExample(buf []byte, off flatbuffers.UOffsetT, fail func(string, ... _ = example.MonsterEnd(builder) } +func CheckCreateByteVector(fail func(string, ...interface{})) { + raw := [30]byte{} + for i := 0; i < len(raw); i++ { + raw[i] = byte(i) + } + + for size := 0; size < len(raw); size++ { + b1 := flatbuffers.NewBuilder(0) + b2 := flatbuffers.NewBuilder(0) + b1.StartVector(1, size, 1) + for i := size - 1; i >= 0; i-- { + b1.PrependByte(raw[i]) + } + b1.EndVector(size) + b2.CreateByteVector(raw[:size]) + CheckByteEquality(b1.Bytes, b2.Bytes, fail) + } +} + // Include simple random number generator to ensure results will be the // same cross platform. // http://en.wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator