`

Google FlatBuffers——开源、跨平台的新一代序列化工具

 
阅读更多

前段时间刚试用了一个序列化工具cereal,请看cereal:C++实现的开源序列化库,打算再总结下我对google proto buf序列化库的使用呢,

结果还没动手,大Google又出了一个新的、开源、跨平台的序列化工具:FlatBuffers。那就索性先了解了解这个工具把。

一. 什么是Google FlatBuffers

FlatBuffers是一个开源的、跨平台的、高效的、提供了C++/Java接口的序列化工具库。它是Google专门为游戏开发或其他性能敏感的应用程序需求而创建。尤其更适用于移动平台,这些平台上内存大小及带宽相比桌面系统都是受限的,而应用程序比如游戏又有更高的性能要求。它将序列化数据存储在缓存中,这些数据既可以存储在文件中,又可以通过网络原样传输,而不需要任何解析开销。

代码托管主页:https://github.com/google/flatbuffers

项目介绍主页:http://google.github.io/flatbuffers/index.html

二. 为什么要使用Google FlatBuffers

  1. 对序列化数据的访问不需要打包和拆包——它将序列化数据存储在缓存中,这些数据既可以存储在文件中,又可以通过网络原样传输,而没有任何解析开销;
  2. 内存效率和速度——访问数据时的唯一内存需求就是缓冲区,不需要额外的内存分配。 这里可查看详细的基准测试
  3. 扩展性、灵活性——它支持的可选字段意味着不仅能获得很好的前向/后向兼容性(对于长生命周期的游戏来说尤其重要,因为不需要每个新版本都更新所有数据);
  4. 最小代码依赖——仅仅需要自动生成的少量代码和一个单一的头文件依赖,很容易集成到现有系统中。再次,看基准部分细节;
  5. 强类型设计——尽可能使错误出现在编译期,而不是等到运行期才手动检查和修正;
  6. 使用简单——生成的C++代码提供了简单的访问和构造接口;而且如果需要,通过一个可选功能可以用来在运行时高效解析Schema和类JSON格式的文本;
  7. 跨平台——支持C++11、Java,而不需要任何依赖库;在最新的gcc、clang、vs2010等编译器上工作良好;

三. 为什么不使用Protocol Buffers的,或者JSON

Protocol Buffers的确和FlatBuffers比较类似,但其主要区别在于FlatBuffers在访问数据前不需要解析/拆包这一步。 而且Protocol Buffers既没有可选的文本导入/导出功能,也没有Schemas语法特性(比如union)。

JSON是非常可读的,而且当和动态类型语言(如JavaScript)一起使用时非常方便。然而在静态类型语言中序列化数据时,JSON不但具有运行效率低的明显缺点,而且会让你写更多的代码来访问数据(这个与直觉相反)。

想了解更多关于FlatBuffers的“为什么”请访问flatbuffers白皮书

四. 内建的数据类型 

  • 8 bit: byte ubyte bool
  • 16 bit: short ushort
  • 32 bit: int uint float
  • 64 bit: long ulong double
  • Vector of any other type (denoted with [type]). Nesting vectors is not supported, instead you can wrap the inner vector in a table.
  • string, which may only hold UTF-8 or 7-bit ASCII. For other text encodings or general binary data use vectors ([byte] or [ubyte]) instead.
  • References to other tables or structs, enums or unions.

详细介绍请参考:schema语法格式。 

五. 如何使用

  1. 编写一个用来定义你想序列化的数据的schema文件(又称IDL),数据类型可以是各种大小的int、float,或者是string、array,或者另一对象的引用,甚至是对象集合;
  2. 各个数据属性都是可选的,且可以设置默认值。
  3. 使用FlatBuffer编译器flatc生成C++头文件或者Java类,生成的代码里额外提供了访问、构造序列化数据的辅助类。生成的代码仅仅依赖flatbuffers.h;请看如何生成
  4. 使用FlatBufferBuilder类构造一个二进制buffer。你可以向这个buffer里循环添加各种对象,而且很简单,就是一个单一函数调用;
  5. 保存或者发送该buffer
  6. 当再次读取该buffer时,你可以得到这个buffer根对象的指针,然后就可以简单的就地读取数据内容;

六. 一个简单的Schemas(IDL)文件

复制代码
namespace zl.persons;  
  
enum GENDER_TYPE : byte  
{  
    MALE    = 0,  
    FEMALE  = 1,  
    OTHER   = 2  
}  
  
table personal_info  
{  
    id : uint;  
    name : string;  
    age : byte;  
    gender : GENDER_TYPE;  
    phone_num : ulong;  
}  
  
table personal_info_list  
{  
    info : [personal_info];  
}  
  
root_type personal_info_list;
复制代码

注意:这里有table、struct的区别:
table是Flatbuffers中用来定义对象的主要方式,和struct最大的区别在于:它的每个字段都是可选的(类似protobuf中的optional字段),而struct的所有成员都是required。
table除了成员名称和类型之外,还可以给成员一个默认值,如果不显式指定,则默认为0(或空)。struct不能定义scalar成员,比如说string类型的成员。在生成C++代码时,struct的成员顺序会保持和IDL的定义顺序一致,如果有必要对齐,生成器会自动生成用于对齐的额外成员。如以下Schemas代码:

struct STest
{
    a : int;
    b : int;
    c : byte;
}

在生成为C++代码之后,会补充两个用于padding的成员__padding0与__padding1:

复制代码
MANUALLY_ALIGNED_STRUCT(4) STest {
 private:
  int32_t a_;
  int32_t b_;
  int8_t c_;
  int8_t __padding0;
  int16_t __padding1;
 
 public:
  STest(int32_t a, int32_t b, int8_t c)
    : a_(flatbuffers::EndianScalar(a)), b_(flatbuffers::EndianScalar(b)), c_(flatbuffers::EndianScalar(c)), __padding0(0) {}
 
  int32_t a() const { return flatbuffers::EndianScalar(a_); }
  int32_t b() const { return flatbuffers::EndianScalar(b_); }
  int8_t c() const { return flatbuffers::EndianScalar(c_); }
};
STRUCT_END(STest, 12);
复制代码

table的成员顺序是动态调整的,这和struct有区别。在生成C++代码时,生成器会自动调整为最佳顺序以保证它占用最小的内存空间。

七. 一个完整Demo

这里只给一个函数演示如何对对象进行序列化,完整工程请直接点击下载,或者前往github查看google_flatbuffers_test

复制代码
std::string CreateOnePerson()
{
    flatbuffers::FlatBufferBuilder builder;
    fb_offset<fb_string> name = builder.CreateString("hello word");

    zl::persons::personal_infoBuilder pib(builder);
    pib.add_id(1);
    pib.add_age(25);
    pib.add_gender(zl::persons::GENDER_TYPE_MALE);
    pib.add_name(name);
    pib.add_phone_num(1234567890);
    flatbuffers::Offset<zl::persons::personal_info> personinfo = pib.Finish();

    fb_offset<zl::persons::personal_info> info[1];
    info[0] = personinfo;

    fb_offset<fb_vector<fb_offset<zl::persons::personal_info>>> info_array = fb_create_vector(builder, info, sizeof(info) / sizeof(info[0]));
    fb_offset<zl::persons::personal_info_list> info_list = create_personal_info_list(builder, info_array);
    fb_finish(builder, info_list);

    // return the buffer for the caller to use.
    return std::string(reinterpret_cast<const char *>(builder.GetBufferPointer()), builder.GetSize());
}
复制代码

八. 其他

关于性能,除了Google公布的基准测试外,有人自己测试验证过,上面的IDL文件即来源于该作者的这篇文章

九. 参考

http://google.github.io/flatbuffers/index.html

http://powman.org/archives/md__schemas.html

http://blog.csdn.net/menggucaoyuan/article/details/34409433

http://liubin.org/2014/06/19/google-flatbuffers-cross-platform-serialization-library/

分享到:
评论

相关推荐

    C++设计模式--基于Qt4开源跨平台开发框架

    《C++设计模式--基于Qt4开源跨平台开发框架》一书主要探讨了如何在C++编程中利用设计模式,并结合Qt4框架进行高效的跨平台应用开发。设计模式是软件工程中的重要概念,它们是经过时间和实践验证的解决特定问题的模板...

    5C++设计模式--基于Qt4开源跨平台开发框架 完整清晰版中文PDF.zip

    好东西一定得分享,自己现阶段需要好好学习一下QT。C++设计模式--基于Qt4开源跨平台开发框架 完整清晰版中文PDF。好东西而且分数不贵!解压密码qt。

    Java反序列化工具.zip

    描述中的"weblogic反序列化工具"和"jboss反序列化工具"提到了两个特定的应用服务器——WebLogic和JBoss。WebLogic是Oracle公司的一个企业级应用服务器,而JBoss则是Red Hat公司的开源Java EE应用服务器。这两个...

    极速五笔——开源输入法

    【极速五笔——开源输入法】是一款以快速、高效为特点的中文输入法软件,它以开源的形式提供给用户,鼓励社区参与开发和优化。开源意味着源代码对公众开放,任何人都可以查看、学习、修改并分发代码,这使得极速五笔...

    ASP.NET源码——开源WEB在线SQL管理工具.zip

    这个压缩包"ASP.NET源码——开源WEB在线SQL管理工具.zip"包含了一个基于ASP.NET的开源项目,允许用户通过Web界面进行SQL数据库的在线管理和操作。这样的工具对于开发者和DBA来说非常实用,因为它提供了远程访问和...

    微软开源跨平台移动开发实践 源码

    本书系统介绍了微软新一代高效、跨平台的应用平台.NET Core 1.0。借助.NET Core,原本只能运行在Windows 上的.NET 应用可以运行在Linux、OS X甚至是UNIX上。结合微软的Apache Cordova 和Xamarin 等工具,可以构建从...

    c++设计模式--基于Qt4开源跨平台开发框架(源代码)

    c++设计模式--基于Qt4开源跨平台开发框架(源代码)c++设计模式--基于Qt4开源跨平台开发框架(源代码)c++设计模式--基于Qt4开源跨平台开发框架(源代码)c++设计模式--基于Qt4开源跨平台开发框架(源代码)c++设计模式--...

    安卓Android源码——开源中国社区项目源码.zip

    安卓Android源码——开源中国社区项目源码.zip

    开源技术大会2014-LarryWall演讲《无心插柳——开源萌发在那个春天》

    开源技术大会2014上,Perl编程语言的创始人拉里·沃尔(Larry Wall)的演讲题目为《无心插柳——开源萌发在那个春天》。在这次演讲中,拉里·沃尔分享了开源技术早期发展的历史,并探讨了开源精神及其与创新之间的...

    FileZilla3.5——免费开源且跨平台的FTP解决方案

    FileZilla是一个免费开源且跨平台的FTP解决方案,分为客户端版本和服务器版本,具备所有的FTP软件功能。在Windows, Linux, MacOS X下的均有对应的版本。软件许可证为GPL。可控性、有条理的界面和管理多站点的简化...

    xlsxtools游戏配置表工具,开源跨平台,支持多语言

    xlsxtools游戏配置表工具,开源跨平台,支持多语言。Unity3D等游戏引擎使用Excel做游戏配置表的解决方案,将xlsx文件转换成txt文本文件,并生成解析代码的工具。已支持C#,Java,OC,即将支持C/C++等

    google开源的数据序列化工具Protocol Buffers.zip

    Protocol Buffers (ProtocolBuffer/ protobuf )是Google公司开发的一种数据描述语言,类似于XML能够将结构化数据序列化,可用于数据存储、通信协议等方面。现阶段支持C 、JAVA、Python等三种编程语言。 为什么不只...

    藏经阁-云上DevOps开发布局——开源与集成DevOps on A.pdf

    藏经阁-云上DevOps开发布局——开源与集成DevOps on A.pdf 在云计算时代,云原生架构设计与应用成为了云计算的“最后一公里”问题。 Framework- 微服务架构、Container Runtime- 容器化、资源生命周期自动化、...

    Seafile——开源的文件云存储平台

    Seafile是一个面向企业的文件云存储系统,目的是解决文件管理、共享和跨平台访问等问题。在此基础上,Seafile提供群组协作的功能,形成一个以文档为中心的协作平台。Seafile项目创始人潘凌涛在开源力量公开课2013...

    kotlinx.serialization,Kotlin跨平台/多格式序列化.zip

    Kotlinx.Serialization是一个强大的开源库,专门为Kotlin编程语言提供了跨平台的序列化解决方案。这个库允许开发者将数据对象转换成字节流或JSON等不同格式,反之亦然,这对于数据交换、存储和网络通信至关重要。它...

    一款基于Qt的跨平台开源串口调试助手EasySerial

    串口调试助手在调试串口设备是非常适用的一个工具,在Windows有很多很好用的串口调试助手,但是在Linux系统上好像还没找到一个好用的带界面的软件(用命令行调试的工具还是有很多的),但是总感觉没有那么方便使用。...

    对象序列化_跨语言(C# )wox开源项目源码

    wox项目很可能是一个跨平台的搜索工具,它利用对象序列化来处理和传输数据,尤其是在与不同编程语言交互时。C#的对象序列化通常涉及到以下关键知识点: 1. **System.Runtime.Serialization命名空间**:C#中的对象...

    一个基于 DotNetty 的轻量级跨平台TCP网关的Socket转发工具,支持docker容器化部署.rar

    今天给大家介绍一个开源的轻量级跨平台实时HTML+C#.NET Web应用程序开发框架——DotNetify,允许你在C#.NET后端上创建具有React、React Native、Vue或Blazor 前端的实时、响应式、跨平台应用程序。 它的主要特点是...

    基于Java与Kotlin的RedisFront开源跨平台桌面客户端工具设计源码

    RedisFront 是一款开源的跨平台 Redis 桌面客户端工具,支持单机、集群、哨兵模式以及 SSH 隧道连接。该工具的设计源码以 Java 和 Kotlin 为主,包含 203 个文件,其中 Java 源文件 85 个,SVG 图像文件 75 个。...

    Java序列化Jar包

    Protocol Buffers是Google开源的一种数据序列化协议,它定义了一种结构化的数据格式,可以用于各种语言之间的数据交换。相比XML和JSON,Protobuf的序列化结果更小、更快,因为它使用二进制格式。在Java环境中,...

Global site tag (gtag.js) - Google Analytics