Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Go speed testing #165

Merged
merged 11 commits into from
May 12, 2015
64 changes: 51 additions & 13 deletions go/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,38 @@ func NewBuilder(initialSize int) *Builder {
return b
}

// Reset truncates the underlying Builder buffer, facilitating alloc-free
// reuse of a Builder.
func (b *Builder) Reset() {
if b.Bytes != nil {
b.Bytes = b.Bytes[:cap(b.Bytes)]
}

if b.vtables != nil {
b.vtables = b.vtables[:0]
}

if b.vtable != nil {
b.vtable = b.vtable[:0]
}

b.head = UOffsetT(len(b.Bytes))
b.minalign = 1
}

// StartObject initializes bookkeeping for writing a new object.
func (b *Builder) StartObject(numfields int) {
b.notNested()
// use 32-bit offsets so that arithmetic doesn't overflow.
b.vtable = make([]UOffsetT, numfields)
if cap(b.vtable) < numfields || b.vtable == nil {
b.vtable = make([]UOffsetT, numfields)
} else {
b.vtable = b.vtable[:numfields]
for i := 0; i < len(b.vtable); i++ {
b.vtable[i] = 0
}
}

b.objectEnd = b.Offset()
b.minalign = 1
}
Expand Down Expand Up @@ -137,7 +164,7 @@ func (b *Builder) WriteVtable() (n UOffsetT) {
SOffsetT(existingVtable)-SOffsetT(objectOffset))
}

b.vtable = nil
b.vtable = b.vtable[:0]
return objectOffset
}

Expand All @@ -155,13 +182,20 @@ 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...)
}
bytes2 := make([]byte, newSize)
copy(bytes2[newSize-len(b.Bytes):], b.Bytes)
b.Bytes = bytes2

middle := newLen / 2
copy(b.Bytes[middle:], b.Bytes[:middle])
}

// Head gives the start of useful data in the underlying byte buffer.
Expand Down Expand Up @@ -247,16 +281,20 @@ func (b *Builder) EndVector(vectorNumElems int) UOffsetT {

// CreateString writes a null-terminated string as a vector.
func (b *Builder) CreateString(s string) UOffsetT {
return b.CreateByteString([]byte(s))
}

// CreateByteString writes a byte slice as a string (null-terminated).
func (b *Builder) CreateByteString(s []byte) UOffsetT {
b.Prep(int(SizeUOffsetT), (len(s)+1)*SizeByte)
b.PlaceByte(0)

x := []byte(s)
l := UOffsetT(len(x))
l := UOffsetT(len(s))

b.head -= l
copy(b.Bytes[b.head:b.head+l], x)
copy(b.Bytes[b.head:b.head+l], s)

return b.EndVector(len(x))
return b.EndVector(len(s))
}

// CreateByteVector writes a ubyte vector
Expand All @@ -274,7 +312,7 @@ func (b *Builder) CreateByteVector(v []byte) UOffsetT {
func (b *Builder) notNested() {
// Check that no other objects are being built while making this
// object. If not, panic:
if b.vtable != nil {
if len(b.vtable) > 0 {
panic("non-inline data write inside of object")
}
}
Expand Down
7 changes: 6 additions & 1 deletion go/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,15 @@ func (t *Table) Indirect(off UOffsetT) UOffsetT {

// String gets a string from data stored inside the flatbuffer.
func (t *Table) String(off UOffsetT) string {
return string(t.ByteVector(off))
}

// ByteVector gets a byte slice from data stored inside the flatbuffer.
func (t *Table) ByteVector(off UOffsetT) []byte {
off += GetUOffsetT(t.Bytes[off:])
start := off + UOffsetT(SizeUOffsetT)
length := GetUOffsetT(t.Bytes[off:])
return string(t.Bytes[start : start+length])
return t.Bytes[start : start+length]
}

// VectorLen retrieves the length of the vector whose offset is stored at
Expand Down
24 changes: 20 additions & 4 deletions src/idl_gen_go.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,19 @@ static void GetVectorLen(const StructDef &struct_def,
code += "\treturn 0\n}\n\n";
}

// Get a [ubyte] vector as a byte slice.
static void GetUByteSlice(const StructDef &struct_def,
const FieldDef &field,
std::string *code_ptr) {
std::string &code = *code_ptr;

GenReceiver(struct_def, code_ptr);
code += " " + MakeCamel(field.name) + "Bytes(";
code += ") []byte " + OffsetPrefix(field);
code += "\t\treturn rcv._tab.ByteVector(o + rcv._tab.Pos)\n\t}\n";
code += "\treturn nil\n}\n\n";
}

// Get the value of a struct's scalar.
static void GetScalarFieldOfStruct(const StructDef &struct_def,
const FieldDef &field,
Expand Down Expand Up @@ -225,7 +238,7 @@ static void GetStringField(const StructDef &struct_def,
code += " " + MakeCamel(field.name);
code += "() " + TypeName(field) + " ";
code += OffsetPrefix(field) + "\t\treturn " + GenGetter(field.value.type);
code += "(o + rcv._tab.Pos)\n\t}\n\treturn \"\"\n";
code += "(o + rcv._tab.Pos)\n\t}\n\treturn nil\n";
code += "}\n\n";
}

Expand Down Expand Up @@ -288,7 +301,7 @@ static void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
code += NumToString(InlineSize(vectortype)) + "))\n";
code += "\t}\n";
if (vectortype.base_type == BASE_TYPE_STRING) {
code += "\treturn \"\"\n";
code += "\treturn nil\n";
} else {
code += "\treturn 0\n";
}
Expand Down Expand Up @@ -480,6 +493,9 @@ static void GenStructAccessor(const StructDef &struct_def,
}
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
GetVectorLen(struct_def, field, code_ptr);
if (field.value.type.element == BASE_TYPE_UCHAR) {
GetUByteSlice(struct_def, field, code_ptr);
}
}
}

Expand Down Expand Up @@ -557,7 +573,7 @@ static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
// Returns the function name that is able to read a value of the given type.
static std::string GenGetter(const Type &type) {
switch (type.base_type) {
case BASE_TYPE_STRING: return "rcv._tab.String";
case BASE_TYPE_STRING: return "rcv._tab.ByteVector";
case BASE_TYPE_UNION: return "rcv._tab.Union";
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
default:
Expand Down Expand Up @@ -610,7 +626,7 @@ static std::string GenTypeBasic(const Type &type) {
static std::string GenTypePointer(const Type &type) {
switch (type.base_type) {
case BASE_TYPE_STRING:
return "string";
return "[]byte";
case BASE_TYPE_VECTOR:
return GenTypeGet(type.VectorType());
case BASE_TYPE_STRUCT:
Expand Down
2 changes: 2 additions & 0 deletions src/idl_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,8 @@ void Parser::ParseDecl() {
CheckClash("Type", BASE_TYPE_UNION);
CheckClash("_length", BASE_TYPE_VECTOR);
CheckClash("Length", BASE_TYPE_VECTOR);
CheckClash("_byte_vector", BASE_TYPE_STRING);
CheckClash("ByteVector", BASE_TYPE_STRING);
Expect('}');
}

Expand Down
2 changes: 2 additions & 0 deletions tests/GoTest.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ 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=. \
--test.benchtime=3s \
--fuzz=true \
--fuzz_fields=4 \
--fuzz_objects=10000
Expand Down
28 changes: 22 additions & 6 deletions tests/MyGame/Example/Monster.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ func (rcv *Monster) Hp() int16 {
return 100
}

func (rcv *Monster) Name() string {
func (rcv *Monster) Name() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
return rcv._tab.String(o + rcv._tab.Pos)
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return ""
return nil
}

func (rcv *Monster) Inventory(j int) byte {
Expand All @@ -75,6 +75,14 @@ func (rcv *Monster) InventoryLength() int {
return 0
}

func (rcv *Monster) InventoryBytes() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}

func (rcv *Monster) Color() int8 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(16))
if o != 0 {
Expand Down Expand Up @@ -122,13 +130,13 @@ func (rcv *Monster) Test4Length() int {
return 0
}

func (rcv *Monster) Testarrayofstring(j int) string {
func (rcv *Monster) Testarrayofstring(j int) []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(24))
if o != 0 {
a := rcv._tab.Vector(o)
return rcv._tab.String(a + flatbuffers.UOffsetT(j * 4))
return rcv._tab.ByteVector(a + flatbuffers.UOffsetT(j * 4))
}
return ""
return nil
}

func (rcv *Monster) TestarrayofstringLength() int {
Expand Down Expand Up @@ -194,6 +202,14 @@ func (rcv *Monster) TestnestedflatbufferLength() int {
return 0
}

func (rcv *Monster) TestnestedflatbufferBytes() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(30))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}

func (rcv *Monster) Testempty(obj *Stat) *Stat {
o := flatbuffers.UOffsetT(rcv._tab.Offset(32))
if o != 0 {
Expand Down
6 changes: 3 additions & 3 deletions tests/MyGame/Example/Stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ func (rcv *Stat) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Pos = i
}

func (rcv *Stat) Id() string {
func (rcv *Stat) Id() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.String(o + rcv._tab.Pos)
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return ""
return nil
}

func (rcv *Stat) Val() int64 {
Expand Down
Loading