数据序列化与传输 Protocal Buffers 与flatbuffer选型对比
- 1、flatbuffers简介
- 2、flatbuffers VS JSON
- 3、flatbuffers 使用
1、flatbuffers简介
flatbuffer是google的一个跨平台串行化库,开发这个最初是用在游戏项目中,github项目地址FlatBuffer提供了详细的使用文档,可以参考Google.github.io主页上的教程。
2、flatbuffers VS JSON
对于Json我们使用了这么长时间,目前几乎所有的数据传输格式都是Json,我们都知道Json是当今全服务平台的轻量级数据传输格式,Json量级轻,并且可读性强,使用友好却不过时,Json是语言独立的数据格式,但Json转换的时候却耗费较多的时间和内存,Facebook尝试过将所有的App中Json传输都换成使用Flatbuffers,而最终的效果可以参考一下这篇文章,看起来这个确实很有前途。正如facebook展示的那样,遵循Android快速响应界面的16ms原则。
如果你想把项目中所有的Json都替换为flatbuffers,首先要确认项目中真的需要这个,很多时候对性能的影响是潜移默化的,相比而言数据安全更加重要。
下面介绍三个数据序列化的候选方案:
Protocal Buffers:强大,灵活,但是对内存的消耗会比较大,并不是移动终端上的最佳选择。
Nano-Proto-Buffers:基于Protocal,为移动终端做了特殊的优化,代码执行效率更高,内存使用效率更佳。
FlatBuffers:这个开源库最开始是由Google研发的,专注于提供更优秀的性能。
上面这些方案在性能方面的数据对比如下图所示:
Paste_Image.png
Paste_Image.png
为什么flatbuffers这么高效?
1.序列化数据访问不经过转换,即使用了分层数据。这样我们就不需要初始化解析器(没有复杂的字段映射)并且转换这些数据仍然需要时间。
2.flatbuffers不需要申请更多的空间,不需要分配额外的对象。
3、flatbuffers 使用
(1)生成flatc
在使用前我们需要先生成flatc,flatc用来将我们编写的fbs文件转换成Java文件,也可以转换成其他文件,但我们在这里并不关心。
编译FlatBuffers生成flatc,我使用的是CMake工具,我们要先安装cmake。
首先要查看我们的系统中是否安装了gcc和g++编译工具。通过下面两条指令查看。默认情况下是安装了的。
gcc -v
g++ -v
如果没有安装通过下面两条指令安装
yum install gcc
yum install gcc-c++
接下来就需要安装CMake,下载CMake源码进行编译安装
wget https://cmake.org/files/v3.5/cmake-3.5.2.tar.gz
tar -zxvf cmake-3.5.2.tar.gz
cd cmake-3.5.2/
sh bootstrap
make
make install
cd到从git下载下来的文件夹,编译flatc程序
cd flatbuffers/
cmake -G "Unix Makefiles"
make
这样就生成了flatc,和一些其他的可执行文件。
(2)定义Schema,生成Java文件
flatBuffers使用Schema定义数据结构,下面是一个简单的示例。语法较为简单
namespace org.sample;
table People {
name:string;
age:int;
}
root_type People;
将文件命名为sample.fbs,然后通过flatc来编译这个Schema。
./flatc --java sample.fbs
会在目录下生成相关的java文件。
定义Schema:
类型支持:基本的数据类型,只有标量值可以有默认值,非标量(string/vector/table)字段默认不存在时为null。如果指定会报
error: default values currently only supported for scalars
的错误,如果想要指定String类型的默认值可以修改生成的Java文件,虽然不建议这么做。
默认值写法:
age : int = 4 ;
isMe : bool = false;
支持数组写法:
array : [string];
支持自定义数据类型
people : People;
但使用的数据类型必须在同一文件中定义。
(3)终于回到Android Stadio部分
在gradle中添加
compile 'com.github.davidmoten:flatbuffers-java:1.3.0.1'
然后把刚才生成的People的Java问价添加到项目中。
准备活动完成,使用起来就比较方便了。
使用过程中,用到最多的是FlatBufferBuilder。
FlatBufferBuilder builder = new FlatBufferBuilder(0);
int sun = builder.createString("Sun");
//下面向People中填充属性
People.startPeople(builder);
People.addName(builder, sun);
People.addAge(builder, 18);
int tom = People.endPeople(builder);
builder.finish(tom);
ByteBuffer buffer = builder.dataBuffer();
People people = People.getRootAsPeople(buffer);
textView.setText(people.name());
生成FlatBufferBuilder, new的方式传入的参数是内部缓冲区的初始大小。使用的非标量类型需要提前生成offset,offset时缓冲区中已编码的字符串开始的偏移量。添加属性前需要先调用类型的start,变量赋值是以add的方式,赋值完成后调用类型的end方法,然后builder的finish,最后转换成字节buffer用于传输。
取值时通过类型的getRootAs...(buffer)直接拿到对象。
引用: