;table FBSBar { f1:FBSFoo; f2:string; f3:[FBSFoo
; f4_key:[int
; // flatbuffers不支持map f4_value:[FBSFoo
; f5:int; f6:long; f7:float; f8:double; f9:[short
; f10:[long
; // 由于fbs不支持基本类型nullable , 因此还需要单独一组字段或者一个vector标识这些值是否为nullroot_type FBSBar; 然后通过flatc编译schema生成Java/Python/GoLang代码文件 。java: flatc -I=src/main/java/io/ray/fury/benchmark/state -o=src/main/java/ bar.fbs 生成Python/GoLang代码 为了避免把生成的代码提交到代码仓库 , 需要将proto跟构建工具进行集成 , 目前似乎只有bazel构建工具有比较好的集成 , 别的构建工具如maven/gradle等似乎都没有比较好的集成方式 。因为生成的类不符合面向对象设计无法直接添加行为 , 同时已有系统里面已经有了需要被序列化的类型 , 因此也需要将已有类型的对象序列化成flatbuffer格式 。 Flatbuffer序列化代码不仅存在和Protobuf一样代码冗长易出错难维护问题 , 还存在以下问题: 代码不灵活、难写且易出错 。 由于flatbuffer在序列化对象树时需要先深度优先和先序遍历整颗对象树 , 并手动保存每个变长字段的offset到临时状态 , 然后再序列化所有字段偏移或者内联标量值 , 这块代码写起来非常繁琐 , 一旦offset存储出现错误 , 序列化将会出现assert/exception/panic等报错 , 较难排查 。list元素需要按照反向顺序进行序列化不符合直觉 。 由于buffer是从后往前构建 , 因此对于list , 需要将元素逆向依次进行序列化 。不支持map类型 , 需要将map序列化为两个list或者序列化为一个table , 进一步带来了额外的开发成本 。下面是Java的序列化代码 , 大概需要100~150行;处理每个字段是否为null , 大概还需要100行左右代码 。 因此Java序列化大概需要200~250行代码:
public static byte[
serialize(Bar bar) { return buildBar(bar).sizedByteArray();public static FlatBufferBuilder buildBar(Bar bar) { // 这里忽略了空值处理的代码 FlatBufferBuilder builder = new FlatBufferBuilder(); int f2_offset = builder.createString(bar.f2); int[
f3_offsets = new int[bar.f3.size()
; for (int i = 0; ibar.f3.size(); i++) { f3_offsets[i
= buildFoo(builder bar.f3.get(i));int f3_offset = FBSBar.createF3Vector(builder f3_offsets); int f4_key_offset; int f4_value_offset; { int[
keys = new int[bar.f4.size()
; int[
valueOffsets = new int[bar.f4.size()
; int i = 0; for (Map.EntryInteger Fooentry : bar.f4.entrySet()) { keys[i
= entry.getKey(); valueOffsets[i
= buildFoo(builder entry.getValue()); i++;f4_key_offset = FBSBar.createF4KeyVector(builder keys); f4_value_offset = FBSBar.createF4ValueVector(builder valueOffsets);int f9_offset = FBSBar.createF9Vector(builder bar.f9); int f10_offset = FBSBar.createF10Vector(builder bar.f10.stream().mapToLong(x -x).toArray()); FBSBar.startFBSBar(builder); FBSBar.addF1(builder buildFoo(builder bar.f1)); FBSBar.addF2(builder f2_offset); FBSBar.addF3(builder f3_offset); FBSBar.addF4Key(builder f4_key_offset); FBSBar.addF4Value(builder f4_value_offset); FBSBar.addF5(builder bar.f5); FBSBar.addF6(builder bar.f6); FBSBar.addF7(builder bar.f7); FBSBar.addF8(builder bar.f8); FBSBar.addF9(builder f9_offset); FBSBar.addF10(builder f10_offset); builder.finish(FBSBar.endFBSBar(builder)); return builder;public static int buildFoo(FlatBufferBuilder builder Foo foo) { int stringOffset = builder.createString(foo.f1); int[
keyOffsets = new int[foo.f2.size()
; int[
values = new int[foo.f2.size()
; int i = 0; for (Map.EntryString Integerentry : foo.f2.entrySet()) { keyOffsets[i
= builder.createString(entry.getKey()); values[i
= entry.getValue(); i++;int keyOffset = FBSFoo.createF2KeyVector(builder keyOffsets); int f2ValueOffset = FBSFoo.createF2ValueVector(builder values); return FBSFoo.createFBSFoo(builder stringOffset keyOffset f2ValueOffset);public static Bar deserializeBar(ByteBuffer buffer) { Bar bar = new Bar(); FBSBar fbsBar = FBSBar.getRootAsFBSBar(buffer); bar.f1 = deserializeFoo(fbsBar.f1()); bar.f2 = fbsBar.f2(); { ArrayListFoof3List = new ArrayList(); for (int i = 0; ifbsBar.f3Length(); i++) { f3List.add(deserializeFoo(fbsBar.f3(i)));bar.f3 = f3List;{ MapInteger Foof4 = new HashMap(); for (int i = 0; ifbsBar.f4KeyLength(); i++) { f4.put(fbsBar.f4Key(i) deserializeFoo(fbsBar.f4Value(i)));bar.f4 = f4;bar.f5 = fbsBar.f5(); bar.f6 = fbsBar.f6(); bar.f7 = fbsBar.f7(); bar.f8 = fbsBar.f8(); { short[
- 中远海运特运首艘加装高压岸电系统船舶“天恩”轮通过测试
- “我们是元宇宙的领路人”|元宇宙,是QQ秀的轮回吗?
- AirPods|世界顶尖技术横空出世,全球只有我国掌握,如今轮到美国卡脖子!
- 36氪|36氪首发丨主打解腻、解渴、解乏的中国茶,「别样泡泡」完成千万级天使轮融资
- 卫星|36氪首发|专注卫星测控通信市场,「讯联科技」获得数千万A+轮融资
- 36氪首发 | 专注于研发医学营养食品,「玛士撒拉」获峰瑞资本独投的数千万元A轮融资
- 小米科技|新一轮价格战爆发?3999元的骁龙8Gen2旗舰机来了,等等党有福了
- B轮融资|曾经很火的迅雷,为什么现在不怎么火了?
- 创投圈|REVA获得a16z 2000万美金融资 WEB3.0教父再次出手
- Java|REVA获得a16z 2000万美金融资 WEB3.0教父再次出手
