Add CreateByteVector function to Go's builder
authorBen Harper <rogojin@gmail.com>
Sun, 8 Mar 2015 19:39:01 +0000 (21:39 +0200)
committerWouter van Oortmerssen <wvo@google.com>
Thu, 12 Mar 2015 00:27:39 +0000 (17:27 -0700)
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
tests/go_test.go

index 94e7e95..e1b1f43 100644 (file)
@@ -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:
index a949635..03eaddf 100644 (file)
@@ -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