-
-
Save tranngoclam/98eb918de5af3ef003cf3722a09e66fd to your computer and use it in GitHub Desktop.
Flat Buffers with Golang
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// automatically generated, do not modify | |
package encoder | |
import ( | |
flatbuffers "github.com/google/flatbuffers/go" | |
) | |
type Container struct { | |
_tab flatbuffers.Table | |
} | |
func GetRootAsContainer(buf []byte, offset flatbuffers.UOffsetT) *Container { | |
n := flatbuffers.GetUOffsetT(buf[offset:]) | |
x := &Container{} | |
x.Init(buf, n + offset) | |
return x | |
} | |
func (rcv *Container) Init(buf []byte, i flatbuffers.UOffsetT) { | |
rcv._tab.Bytes = buf | |
rcv._tab.Pos = i | |
} | |
func (rcv *Container) Testarrayofmonsters(obj *Monster, j int) bool { | |
o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) | |
if o != 0 { | |
x := rcv._tab.Vector(o) | |
x += flatbuffers.UOffsetT(j) * 4 | |
x = rcv._tab.Indirect(x) | |
if obj == nil { | |
obj = new(Monster) | |
} | |
obj.Init(rcv._tab.Bytes, x) | |
return true | |
} | |
return false | |
} | |
func (rcv *Container) TestarrayofmonstersLength() int { | |
o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) | |
if o != 0 { | |
return rcv._tab.VectorLen(o) | |
} | |
return 0 | |
} | |
func ContainerStart(builder *flatbuffers.Builder) { builder.StartObject(1) } | |
func ContainerAddTestarrayofmonsters(builder *flatbuffers.Builder, testarrayofmonsters flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(testarrayofmonsters), 0) } | |
func ContainerStartTestarrayofmonstersVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { return builder.StartVector(4, numElems, 4) | |
} | |
func ContainerEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// flat_buffers.fbs | |
// namespace encoder; | |
// brew install flatbuffers | |
// flatc -g flat_buffers.fbs | |
table Container { | |
testarrayofmonsters:[Monster]; | |
} | |
table Monster { | |
name:string; | |
phone:string; | |
birthday:double; | |
money:double; | |
siblings:short; | |
spouse:bool; | |
strings:[string]; | |
} | |
root_type Container; | |
file_identifier "MONS"; | |
file_extension "mon"; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package encoder | |
// Flat Buffers | |
// Encode/Decode time: 0.430/0.285 | |
import ( | |
"testing" | |
"github.com/stretchr/testify/assert" | |
"github.com/google/flatbuffers/go" | |
"io/ioutil" | |
"time" | |
"fmt" | |
) | |
func TestMarshalFlatbuf(t *testing.T) { | |
builder := flatbuffers.NewBuilder(0) | |
name := builder.CreateString("alex") | |
str1 := builder.CreateString("str1") | |
str2 := builder.CreateString("str2") | |
MonsterStartStringsVector(builder, 2) | |
builder.PrependUOffsetT(str2) | |
builder.PrependUOffsetT(str1) | |
stringArr := builder.EndVector(2) | |
MonsterStart(builder) | |
MonsterAddName(builder, name) | |
MonsterAddMoney(builder, 1.345) | |
MonsterAddStrings(builder, stringArr) | |
monster := MonsterEnd(builder) | |
builder.Finish(monster) | |
b := builder.Bytes[builder.Head():] | |
n := flatbuffers.GetUOffsetT(b) | |
dec := &Monster{} | |
dec.Init(b, n) | |
assert.Equal(t, []byte("alex"), dec.Name()) | |
assert.Equal(t, 1.345, dec.Money()) | |
assert.Equal(t, 2, dec.StringsLength()) | |
assert.Equal(t, []byte("str1"), dec.Strings(0)) | |
assert.Equal(t, []byte("str2"), dec.Strings(1)) | |
data:= generate() | |
tim := time.Now() | |
encode(data) | |
fmt.Println(time.Since(tim)) | |
} | |
func BenchmarkFlatbufCompress(b *testing.B) { | |
b.StopTimer() | |
data := generate() | |
b.ReportAllocs() | |
b.StartTimer() | |
var enc []byte | |
for n := 0; n < b.N; n++ { | |
enc = encode(data) | |
} | |
ioutil.WriteFile("data_flatbuff.txt", enc, 0666) | |
} | |
func BenchmarkFlatbufDecompress(b *testing.B) { | |
b.ReportAllocs() | |
input, _ := ioutil.ReadFile("data_flatbuff.txt") | |
var total time.Duration | |
for n := 0; n < b.N; n++ { | |
tm := time.Now() | |
decode(input) | |
total += time.Since(tm) | |
} | |
} | |
func encode(data ASlice)[]byte{ | |
b := flatbuffers.NewBuilder(0) | |
ptrs := make([]flatbuffers.UOffsetT, len(data)) | |
for i := 0;i < len(data);i++ { | |
value := data[i] | |
name := b.CreateString(value.Name) | |
phone := b.CreateString(value.Phone) | |
MonsterStart(b) | |
MonsterAddName(b, name) | |
MonsterAddPhone(b, phone) | |
MonsterAddMoney(b, value.Money) | |
MonsterAddBirthday(b, float64(value.BirthDay.UnixNano())) | |
MonsterAddSiblings(b, int16(value.Siblings)) | |
bt := byte(0x0) | |
if value.Spouse { | |
bt = 0x1 | |
} | |
MonsterAddSpouse(b, bt) | |
monster := MonsterEnd(b) | |
ptrs[i] = monster | |
} | |
ContainerStartTestarrayofmonstersVector(b, len(ptrs)) | |
for i := len(ptrs)-1;i >= 0;i-- { | |
b.PrependUOffsetT(ptrs[i]) | |
} | |
vptr := b.EndVector(len(ptrs)) | |
ContainerStart(b) | |
ContainerAddTestarrayofmonsters(b, vptr) | |
container := ContainerEnd(b) | |
b.Finish(container) | |
return b.Bytes[b.Head():] | |
} | |
func decode(input []byte) { | |
cont := GetRootAsContainer(input, 0) | |
res:= make(ASlice, cont.TestarrayofmonstersLength()) | |
for i := 1; i < len(res);i++{ | |
m := &Monster{} | |
cont.Testarrayofmonsters(m, i) | |
a := A{ | |
Name:string(m.Name()), | |
Phone:string(m.Phone()), | |
Money:m.Money(), | |
BirthDay:time.Unix(int64(m.Birthday())/int64(time.Millisecond), 0), | |
Siblings:int32(m.Siblings()), | |
} | |
if m.Spouse() == 0x1 { | |
a.Spouse = true | |
} | |
res[i]=a | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// automatically generated, do not modify | |
package encoder | |
import ( | |
flatbuffers "github.com/google/flatbuffers/go" | |
) | |
type Monster struct { | |
_tab flatbuffers.Table | |
} | |
func (rcv *Monster) Init(buf []byte, i flatbuffers.UOffsetT) { | |
rcv._tab.Bytes = buf | |
rcv._tab.Pos = i | |
} | |
func (rcv *Monster) Name() []byte { | |
o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) | |
if o != 0 { | |
return rcv._tab.ByteVector(o + rcv._tab.Pos) | |
} | |
return nil | |
} | |
func (rcv *Monster) Phone() []byte { | |
o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) | |
if o != 0 { | |
return rcv._tab.ByteVector(o + rcv._tab.Pos) | |
} | |
return nil | |
} | |
func (rcv *Monster) Birthday() float64 { | |
o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) | |
if o != 0 { | |
return rcv._tab.GetFloat64(o + rcv._tab.Pos) | |
} | |
return 0 | |
} | |
func (rcv *Monster) Money() float64 { | |
o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) | |
if o != 0 { | |
return rcv._tab.GetFloat64(o + rcv._tab.Pos) | |
} | |
return 0 | |
} | |
func (rcv *Monster) Siblings() int16 { | |
o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) | |
if o != 0 { | |
return rcv._tab.GetInt16(o + rcv._tab.Pos) | |
} | |
return 0 | |
} | |
func (rcv *Monster) Spouse() byte { | |
o := flatbuffers.UOffsetT(rcv._tab.Offset(14)) | |
if o != 0 { | |
return rcv._tab.GetByte(o + rcv._tab.Pos) | |
} | |
return 0 | |
} | |
func (rcv *Monster) Strings(j int) []byte { | |
o := flatbuffers.UOffsetT(rcv._tab.Offset(16)) | |
if o != 0 { | |
a := rcv._tab.Vector(o) | |
return rcv._tab.ByteVector(a + flatbuffers.UOffsetT(j * 4)) | |
} | |
return nil | |
} | |
func (rcv *Monster) StringsLength() int { | |
o := flatbuffers.UOffsetT(rcv._tab.Offset(16)) | |
if o != 0 { | |
return rcv._tab.VectorLen(o) | |
} | |
return 0 | |
} | |
func MonsterStart(builder *flatbuffers.Builder) { builder.StartObject(7) } | |
func MonsterAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0) } | |
func MonsterAddPhone(builder *flatbuffers.Builder, phone flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(phone), 0) } | |
func MonsterAddBirthday(builder *flatbuffers.Builder, birthday float64) { builder.PrependFloat64Slot(2, birthday, 0) } | |
func MonsterAddMoney(builder *flatbuffers.Builder, money float64) { builder.PrependFloat64Slot(3, money, 0) } | |
func MonsterAddSiblings(builder *flatbuffers.Builder, siblings int16) { builder.PrependInt16Slot(4, siblings, 0) } | |
func MonsterAddSpouse(builder *flatbuffers.Builder, spouse byte) { builder.PrependByteSlot(5, spouse, 0) } | |
func MonsterAddStrings(builder *flatbuffers.Builder, strings flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(6, flatbuffers.UOffsetT(strings), 0) } | |
func MonsterStartStringsVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { return builder.StartVector(4, numElems, 4) | |
} | |
func MonsterEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type ASlice []A | |
type AStruct struct{ | |
Slice ASlice | |
} | |
type A struct { | |
Name string | |
BirthDay time.Time | |
Phone string | |
Siblings int32 | |
Spouse bool | |
Money float64 | |
} | |
func randString(l int) string { | |
buf := make([]byte, l) | |
for i := 0; i < (l+1)/2; i++ { | |
buf[i] = byte(rand.Intn(256)) | |
} | |
return fmt.Sprintf("%x", buf)[:l] | |
} | |
func generate() ASlice { | |
a := make(ASlice, 0, 1000) | |
for i := 0; i < 1000; i++ { | |
a = append(a, A{ | |
Name: randString(16), | |
BirthDay: time.Now(), | |
Phone: randString(10), | |
Siblings: int32(rand.Intn(5)), | |
Spouse: rand.Intn(2) == 1, | |
Money: rand.Float64(), | |
}) | |
} | |
return a | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment