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白皮书

四. 如何使用

  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/

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

时间: 2024-11-11 07:07:24

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

Brackets - 强大免费的开源跨平台Web前端开发工具IDE (HTML/CSS/Javascript代码编辑器)

Brackets 是一个免费.开源且跨平台的 HTML/CSS/JavaScript 前端 WEB 集成开发环境 (IDE工具).该项目由 Adobe 创建和维护,根据MIT许可证发布,支持 Windows.Linux 以及 OS X 平台. Brackets 的特点是简约.优雅.快捷!它没有很多的视图或者面板,也没太多花哨的功能,它的核心目标是减少在开发过程中那些效率低下的重复性工作,例如浏览器刷新,修改元素的样式,搜索功能等等.和 Sublime Text.Everedit 等通用代码编辑器

开源跨平台数据格式化框架概览

说到数据格式化框架,就不得不提到 Google 的 Protocol Buffers,Facebook 的 Thrift,还有 Apache Hadoop 推出的 Avro.Microsoft 最近开源的 Bond 也是一种用于数据格式化的可扩展框架,其适用的应用场景包括服务间通信.大数据存储和处理等. 为什么会有这么多关于数据格式处理的框架?它们都在解决什么问题呢?我们先来观察一下典型的服务间通信的结构. 通常,在设计服务间通信时,我们所要面对的基本问题有: 如何传输数据? 使用什么协议通信?

Java序列化工具对比

1. Java序列化工具技术原理比较 Binary Formats & language-specific ones JavaBuiltIn(java原生).JavaManual(根据成员变量类型,手工写).FstSerliazation.Kryo Binary formats-generic language-unspecific ones Protobuf(Google).Thrift(Facebook). AvroGeneric.Hessian JSON Format Jackson.Gs

C++的开源跨平台日志库glog学习研究(一)

作为C++领域中为数不多的好用.高效的.跨平台的日志工具,Google的开源日志库glog也算是凤毛麟角了.glog 是一个C++实现的应用级日志记录框架,提供了C++风格的流操作. 恰巧趁着五一我也学习研究了这个glog库,写个总结如下.走过路过的的各位牛人.高手可以忽略这篇文章了. 从code.google.com下载源码(在这里),在Visual Studio 2010中打开工程,如下: 可见只有四个工程,其中libglog和libglog_static分别是Windows下的动态库和静态

【新书推荐】《微软开源跨平台移动开发实践》带你走近微软开源开源跨平台技术

上周收到本书作者李争送的一本12月份的新书<微软开源跨平台移动开发实践——利用ASP.NET Core 1.0 .Apache Cordova.Xamarin和Azure快速构建移动应用解决方案>.这本书的名字超长.这本书也是超薄,只有220页,一个周末时间就读完了,但是这本书的内容确是超丰富,浓缩了微软这三年向开源和跨平台领域的转变,微软在开源和跨平台领域构建出来的一套技术体系.从服务端的NET Core.ASP.NET 和 Web APi ,到Web端的 Typescript脚本语言,再到

C#跨平台手机应用开发工具Xamarin尝试 与Eclipse简单对比

Xamarin 支持使用C#开发基于Android.IOS.WindowsPhone应用开发,最大特点C#+跨平台,详细说明问度娘. 安装 研究 想体验研究的点击查看页面 Xamarin For Visual Studio 3.0.54.0 完整离线破解版 我也下载了研究下,破解有时候有问题,一登陆就变成试用版,需要重新生成License,挺烦人,于是写了段批处理,放入记事本中另存为crack.bat执行,则可再次生成License. @Entitlements.bak为破解后生成的Entitl

Fedora 25 (linux平台)开源的PDF文件编辑工具——PDF mod

Fedora 25 (linux平台)开源的PDF文件编辑工具--PDF mod PDF文件具有非常好的跨平台属性,无论你在哪个平台用哪个PDF阅读器打开,其格式是永远不变的.但是缺点也很明显,文本文件或者图文混排文件,要想再次编辑就有很大难度了. Document viewer作为fedora 25默认PDF阅读器,用来阅读PDF文件没什么大问题,但是如果要修改一下PDF就显得不够强大了. PDF Mod是一款编辑 PDF 文件很方便的工具.包名:pdfmod PDF Mod 让用户可以移除页

微软开源跨平台移动开发实践(文摘)

第1章 微软“云+端”战略 第2章 革命性的asp.net core asp.net core 的新特性: 1.使用JSON格式配置文件 2.使用OWIN与IIS解耦 3.全新的HttpContext 4.内置依赖注入 5.支持开发的包管理工具 6.采用即时编译运行 mvc 6的新特性: 1.合并技术栈 2.改进路由功能 3.模型绑定 4.TagHelper 第3章 开源跨平台额设备端开发 1.QT Library介绍 2.Xamarin介绍 3.Cordova介绍 第4章 项目介绍和需求分析

C++的开源跨平台日志库glog学习研究(二)--宏的使用

上一篇从整个工程上简单分析了glog,请看C++的开源跨平台日志库glog学习研究(一),这一篇对glog的实现代码入手,比如在其源码中以宏的使用最为广泛,接下来就先对各种宏的使用做一简单分析. 1. 日志输出宏 这里我们以一条最简单的日至输出为例说明: LOG(WARNING) << "This is a warning message"; 这里LOG是一个宏,其定义如下(logging.h line 487): #define LOG(severity) COMPACT