内容简介:FlatBuffers是Google开源的一个跨平台的、高效的、提供了C++/Java接口的序列化工具库,它是Google专门为游戏开发或其他性能敏感的应用程序需求而创建。尤其适用移动,嵌入式平台,这些平台在内存大小及带宽相比桌面系统都是受限的,而应用程序比如游戏又有更高的性能要求。它将序列化数据存储在缓存中,这些数据既可以存储在文件中,又可以通过网络原样传输,而不需要任何解析开销。以下是项目地址: 代码托管主页:相比传统的JSON和Protocol Buffers等序列化工具,FlatBuffers具有
FlatBuffers是Google开源的一个跨平台的、高效的、提供了C++/Java接口的序列化 工具 库,它是Google专门为游戏开发或其他性能敏感的应用程序需求而创建。尤其适用移动,嵌入式平台,这些平台在内存大小及带宽相比桌面系统都是受限的,而应用程序比如游戏又有更高的性能要求。它将序列化数据存储在缓存中,这些数据既可以存储在文件中,又可以通过网络原样传输,而不需要任何解析开销。以下是项目地址: 代码托管主页: github.com/google/flat… 项目介绍主页: google.github.io/flatbuffers…
FlatBuffers优势
相比传统的JSON和Protocol Buffers等序列化工具,FlatBuffers具有如下的一些优点:
- 不需要解析/拆包就可以访问序列化数据 :FlatBuffers与其他库不同之处就在于它使用二进制缓冲文件来表示层次数据,这样它们就可以被直接访问而不需解析与拆包,同时还支持数据结构进化(前进、后退兼容性)。
- 内存高效速度快 :访问数据时只需要访问内存中的缓冲区。它不需要多余的内存分配(至少在C++是这样,其他语言中可能会有变动)。 FlatBuffers还适合配合 mmap或数据流使用,只需要缓冲区的一部分存储在内存中。访问时速度接近原结构访问,只有一点延迟(一种虚函数表vtable),是为了允许格式升级以 及可选字段。FlatBuffers适合那些花费了大量时间和空间(内存分配)来访问和构建序列化数据的项目,比如游戏以及其他对表现敏感的应用。可以参考FlatBuffers基准。
- 灵活 :由于具有可选字段,你不但有很强的升级和回退兼容性(对于历史悠久的游戏尤其重要,不用为了每个版本升级所有数据),在选择要存储哪些数据以及设计数据结构时也很自由。
- 轻量的code footprint :FlatBuffers只需要很少量的生成代码,以及一个表示最小依赖的很小的头文件,很容易集成。
- 强类型 :当编译时报错时,不需要自己写重复的容易出错的运行时检查,它可以自动生成有用的代码。
- 使用方便 :生成的C++代码允许精简访问与构建代码,还有可选的用于实现图表解析、类似JSON的运行时字符串展示等功能的方法。(后者比JSON解析库更快,内存效率更高)。
- 代码跨平台且没有依赖 :C++代码可以运行在任何近代的gcc/clang和VS2010上,同时还有用于测试和范例的构建文件(Android中.mk文件,其他平台是cmake文件)。
VS Protocol Buffers和JSON
Protocol Buffers的确和FlatBuffers比较类似,但其主要区别在于FlatBuffers在访问数据前不需要解析/拆包这一步,而且Protocol Buffers既没有可选的文本导入/导出功能,也没有Schemas语法特性(比如union)。
JSON是一种轻量级的数据交换格式,JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在函数之间轻松地传递这个字符串,或者在异步应用程序中将字符串从 Web 客户机传递给服务器端程序。JSON和动态类型语言(如JavaScript)一起使用时非常方便。然而在静态类型语言中序列化数据时,JSON不但具有运行效率低的明显缺点,而且会让你写更多的代码来访问数据。
FlatBuffers究竟有多提高
- 解析速度 :解析一个20KB的JSON流需要35ms,超过了UI刷新间隔也就是16.6ms。如果解析JSON的话,我们就在滑动时就会因为要从磁盘加载缓存而导致掉帧(视觉上的卡顿)。
- 解析器初始化 :一个JSON解析器需要先构建字段映射再进行解析,这会花100ms到200ms,很明显的拖缓App启动时间。
- 垃圾回收 在解析JSON时创建了很多小对象,在我们的试验中,解析20kb的JSON流时,要分配大约100kb的瞬时存储,对 Java 内存回收造成很大压力。
FlatBuffers实战
FlatBuffers运作流程
首先来看一下FlatBuffers项目为开发者提供了哪些内容,可以从官网下载源码,其目录结构如下图:
如果要将FlatBuffers 用到我们的项目中,又需要哪些流程呢?可以参考下面的流程图:
FlatBuffers用法
就像Parcel和Serializable的序列化一样,FlatBuffers的是使用方式上也比最传统的JSON序列化要复杂的多。在实际上面开发中,为了降低开发的难度,提高开发效率,我们会将源码编译成可植入的第三方库。下面以Java环境为例,来介绍FlatBuffers的简单使用方法。读者可以到对应的maven仓库下载。
现在,假如我们拿到的json文件的格式是下面这样的:
{ "repos": [ { "id": 27149168, "name": "acai", "full_name": "google/acai", "owner": { "login": "google", "id": 1342004, ... "type": "Organization", "site_admin": false }, "private": false, "html_url": "https://github.com/google/acai", "description": "Testing library for JUnit4 and Guice.", ... "watchers": 21, "default_branch": "master" }, ... ] } 复制代码
注:可以通过下面的链接来获取更 完整的json对象
模式文件
我们需要准备一个model文件,它定义了我们想要序列化/反序列化 的数据结构,这个模式将被flatc用于创建Java模型以及从JSON到FlatBuffer二进制文件的转换。
现在,我们所要做的所有事情就是创建3个表:ReposList,Repo和User,并定义root_type。例如:
table ReposList { repos : [Repo]; } table Repo { id : long; name : string; full_name : string; owner : User; //... labels_url : string (deprecated); releases_url : string (deprecated); } table User { login : string; id : long; avatar_url : string; gravatar_id : string; //... site_admin : bool; } root_type ReposList; 复制代码
注:完整的模式文件可以 点击下面的链接 来获取
FlatBuffers文件
接下来,我们所需要做的就是将repos_json.json转换为FlatBuffers二进制文件,并产生Java模型,其可以以Java友好的方式表示我们的数据,下面是转换的命令:
$ ./flatc -j -b repos_schema.fbs repos_json.json 复制代码
如果没有任何报错,将会生成如下4个文件:
repos_json.bin (将被重命名为repos_flat.bin) Repos/Repo.java Repos/ReposList.java Repos/User.java 复制代码
测试
接下来,我们可以使用FlatBuffers提供的Java库来处理在Java中直接处理这种数据格式,此处使用需要使用到 flatbuffers-java-1.2.0-SNAPSHOT.jar 。
public class MainActivity extends AppCompatActivity { @Bind(R.id.tvFlat) TextView tvFlat; @Bind(R.id.tvJson) TextView tvJson; private RawDataReader rawDataReader; private ReposListJson reposListJson; private ReposList reposListFlat; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); rawDataReader = new RawDataReader(this); } @OnClick(R.id.btnJson) public void onJsonClick() { rawDataReader.loadJsonString(R.raw.repos_json).subscribe(new SimpleObserver<String>() { @Override public void onNext(String reposStr) { parseReposListJson(reposStr); } }); } private void parseReposListJson(String reposStr) { long startTime = System.currentTimeMillis(); reposListJson = new Gson().fromJson(reposStr, ReposListJson.class); for (int i = 0; i < reposListJson.repos.size(); i++) { RepoJson repo = reposListJson.repos.get(i); Log.d("FlatBuffers", "Repo #" + i + ", id: " + repo.id); } long endTime = System.currentTimeMillis() - startTime; tvJson.setText("Elements: " + reposListJson.repos.size() + ": load time: " + endTime + "ms"); } @OnClick(R.id.btnFlatBuffers) public void onFlatBuffersClick() { rawDataReader.loadBytes(R.raw.repos_flat).subscribe(new SimpleObserver<byte[]>() { @Override public void onNext(byte[] bytes) { loadFlatBuffer(bytes); } }); } private void loadFlatBuffer(byte[] bytes) { long startTime = System.currentTimeMillis(); ByteBuffer bb = ByteBuffer.wrap(bytes); reposListFlat = frogermcs.io.flatbuffs.model.flat.ReposList.getRootAsReposList(bb); for (int i = 0; i < reposListFlat.reposLength(); i++) { Repo repos = reposListFlat.repos(i); Log.d("FlatBuffers", "Repo #" + i + ", id: " + repos.id()); } long endTime = System.currentTimeMillis() - startTime; tvFlat.setText("Elements: " + reposListFlat.reposLength() + ": load time: " + endTime + "ms"); } } 复制代码
在上面的示例代码中,有两个方法是比较核心的,需要我们注意。
- parseReposListJson(String reposStr) :初始化Gson解析器并将json字符串转换为Java对象。
- loadFlatBuffer(byte[] bytes) 将bytes(即repos_flat.bin文件)转为Java对象。
耗时测试
下面我们来测试下FlatBuffers和传统的json在数据解析上的耗时,我们以4mb的JSON文件为例。
如图,可以发现FlatBuffers花了1-5ms,JSON花了大约2000ms。并且FlatBuffers期间Android App中没有GC,而在使用JSON时发生了很多次GC,测试的源码可以通过以下地址下载:FlatBuffers耗时测试以上所述就是小编给大家介绍的《Android FlatBuffers实战》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 「Flask实战」鱼书项目实战一
- 「Flask实战」鱼书项目实战三
- 「Flask实战」鱼书项目实战四
- 「Flask实战」鱼书项目实战六
- RocketMQ实战系列从理论到实战
- 「Flask实战」flask鱼书项目实战二
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
可爱的Python
哲思社区 / 电子工业出版社 / 2009-9 / 55.00元
本书的内容主要来自CPyUG社区的邮件列表,由Python的行者根据自身经验组织而成,是为从来没有听说过Python的其他语言程序员准备的一份实用的导学性质的书。笔者试图将优化后的学习体验,通过故事的方式传达给读者,同时也分享了蟒样(Pythonic式)的知识获取技巧,而且希望将最常用的代码和思路,通过作弊条(Cheat Sheet,提示表单)的形式分享给有初步基础的Python 用户,来帮助大家......一起来看看 《可爱的Python》 这本书的介绍吧!