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

2023-11-19

前段时间刚试用了一个序列化工具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/



已有 0 人发表留言,猛击->> 这里<<-参与讨论  


ITeye推荐 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • ch01-核心概念 (进阶)

    文章目录 常量 特殊值 空值 无穷 数据类型 类型 大小 顺序 结构化数组 时间数组 数组对象 ndarray array 自定义数组容器 子类化与标准子类 小结 参考 安装watermark pip install watermark l
  • 解决数据库高并发访问瓶颈问题

    一 缓存式的Web应用程序架构 在Web层和db层之间加一层cache层 主要目的 减少数据库读取负担 提高数据读取速度 cache存取的媒介是内存 可以考虑采用分布式的cache层 这样更容易破除内存容量的限制 同时增加了灵活性 二 实现
  • linux创建套接字文件类型,Linux日记---0X03文件类型

    文件类型 文件 文件是文件系统中存储数据的一个命名对象 文件是linux系统处理信息的基本单元 一个文件可以空文件 但空文件仍然为操作系统提供了其他信息 文件组成了linux的一切 linux将数据库文件 游戏文件或者字处理文件都仅仅看做一
  • [学习笔记]Matlab(持续更新)

    文章目录 一 Matlab知识学习 1 输入输出语句 注意 Matlab中disp fprintf及sprintf三者之间的区别 2 exist函数的使用 3 matlab中的注释 4 几种常用的清除命令 5 MAT文件如何操作 6 dir
  • 期货投资如何能少犯错

    无论投资者进行哪种投资 肯定或多或少都会犯错误 毕竟没有谁能保证自己一定不会犯错误 但投资者应该尽量让自己少犯错误 并把这点作为自己追求的目标 投资者如果想要少犯错误 就要尊重市场 不做违背市场规则的操作 其实很多投资者都知道这点 但是当自
  • Mysql-JDBC配置Replication协议

    这部分描述了Mysql JDBC对于replication协议的一系列特性的支持 mysql jdbc replication初始化于创建连接URL阶段 和通常的jdbc URL类似 但也有些特殊性 jdbc mysql replicati
  • 跟大师一起学习环路补偿,图文并茂

    作为工程师 每天接触的是电源的设计工程师 发现不管是电源的老手 高手 新手 几乎对控制环路的设计一筹莫展 基本上靠实验 靠实验当然是可以的 但出问题时往往无从下手 在这里我想以反激电源为例子 在所有拓扑中环路是最难的 由于RHZ 的存在 大
  • wsl安装ubuntu

    WSL 用管理员打开powershell wsl install 重启 用管理员打开powershell 启用适用于 Linux 的 Windows 子系统 dism exe online enable feature featurenam
  • vue3+leaflet+天地图

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 一 准备工作 1 安装插件 2 天地图秘钥 二 使用步骤 1 引入库 2 创建地图容器 3 初始化地图 4 界面效果 天地图地图服务API相关 一 准备工作 需要先
  • Oracle两张表关联批量更新其中一张表的数据

    创建如下表数据 select from t1 select from t2 现需求 参照T2表 修改T1表 修改条件为两表的fname列内容一致 方式1 update 常见陷阱 UPDATE T1 SET T1 FMONEY select
  • 二进制安全虚拟机Protostar靶场 安装,基础知识讲解,破解STACK ZERO

    简介 pwn是ctf比赛的方向之一 也是门槛最高的 学pwn前需要很多知识 这里建议先去在某宝上买一本汇编语言第四版 看完之后学一下python和c语言 python推荐看油管FreeCodeCamp的教程 c语言也是 pwn题目大部分是破
  • 基于python+selenium的二次封装

    这是个人对selenium webdriver写的一些常用操作的二次封装 也就相当于重写了 不再使用自带的框架 用自己写的框架完成 这样的话使代码更简洁 用自己的思想完成代码的编写 首先在根目录下创建子目录名为Common作为公用数据 名字
  • RequireJS 与 AngularJS 集成(完整版)

    JS结构 main js main js这个文件完成的事情简单来说就是 载入所有文件 然后在document上运行Angular并将ng app属性设置为 app 这些文件因为是由RequireJS异步载入 因此我们需要来 手动启动 Ang

随机推荐

  • 逻辑回归原理(python代码实现)

    原文 https blog csdn net csqazwsxedc article details 69690655 Logistic Regression Classifier逻辑回归主要思想就是用最大似然概率方法构建出方程 为最大化方
  • 架构学习笔记—优酷网

    互联网就是这么一个神奇的东西 今天我突然想到 优酷网在国内也算是视频网站的老大了 不知道他的架构相对于YouTube是怎么样的 于是带着这 个好奇心去网上找了优酷网架构的各方面资料 虽然谈的不是那么详细 但多少还是挖掘了一点 现在总结一下
  • 线程和进程的区别(面试必备)

    参考文章 https www jianshu com p 2dc01727be45 线程与进程的区别通俗的解释 https www jianshu com p 8ad441510860 附加可参考文章 https baijiahao bai
  • c#与SQL server知识

    1 数据库建立 在C 中建立的数据库 想要在SQLserver中找到需要连接与c 相同的服务器才可以找到 2 在C 中建立数据库更新不成功 需要打开SQL server 连接与c 相同的服务器 随后在c 中更新 3 在c 界面中更新数据库成
  • maven安装及配置(详细版)

    1 下载 方式一可以从官方下载 下载页面 http maven apache org download cgi 方式二 或者题主提供的版本下载maven安装包 提取码 ysns 下载好后是一个压缩文件 2 安装 maven压缩包解压到一个没
  • 拓展知识 启望未来

    炎炎六月 迎来了备受期待的 亚信科技AntDB数据库初级认证培训 活动 通过培训 希望内蒙古移动及项目组的伙伴们能够系统学习到国产数据库的核心知识 提升专业技能 为服务感知提升 运维团队培育注入新的活力 26号上午 首先由内蒙古移动智慧运维
  • 【10】Docker私有仓库

    一 私有仓库搭建与配置 1 拉取 私有仓库 镜像 docker pull registry 2 创建并启动 私有仓库 容器 docker run di name registry p 5000 5000 registry 打开浏览器输入地址
  • JavaScript Boolean 对象

    解释 Boolean 对象用于转换一个不是 Boolean 类型的值转换为 Boolean 类型值 true 或者false 语法 var a true var b false Boolean 对象属性 属性 描述 constructor
  • 数据结构学习系列之顺序表的两种创建方式

    方式1 通过返回值返回所申请的内存空间的首地址 示例代码 list t create seq list 1 list t p list t malloc sizeof list t if NULL p printf 内存分配失败 n exi
  • linux内核、驱动和硬件之间的关系和通信

    linux驱动是直接和硬件打交道的软件程序 层次结构上 它处于操作系统和硬件之间 驱动与linux内核的关系 驱动程序提供的一组设备驱动接口函数Device Driver Interface给操作系统在linux中 这一组设备驱动接口函数一
  • 前端axios下载excel文件(二进制)的处理方法

    前端axios下载excel文件 二进制 的处理方法 后端生成excel后 前端 click 事件进行下载 脱坑记录 亲测有效 lz 使用的是 axios 发起请求 首先 介绍一下思路 准备通过动态创建 a 标签 通过 blob 对象进行接
  • java调优总结

    JVM调优总结 序 几年前写过一篇关于JVM调优的文章 前段时间拿出来看了看 又添加了一些东西 突然发现 基础真的很重要 学习的过程是一个由表及里 再由里及表的过程 呵呵 所谓的 温故而知新 而真正能走完这个轮回的人 也就能称为大牛或专家了
  • 补充:YOLO模型训练时loss出现nan值或者测试时P\R\map全部为0值的解决办法(GTX16xx系列显卡)

    补充 1 参考1 2 补充 3 小结 1 参考1 在参考有头发的垃圾猿的 YOLO系列训练时出现loss出现nan值或者测试时P R map全部为0值的解决办法 GTX16xx系列显卡大坑 后 发现问题不能得到实际的解决 可能是版本不一样导
  • vs调试正确显示utf8格式字符串

    vs调试正确显示utf8格式字符串 自从将visual studio从2010升级到2015后 发现调用接口的utf8格式字符串不能正常显示了 常常被莫名其妙截断 查了下 原来可以直接将变量拖到watch窗口中 在变量名后面手动添加 s8予
  • 计算机网络的两级子网指,计算机三级网络技术分类练习题_网络基本概念(一).doc...

    您所在位置 网站首页 gt 海量文档 nbsp gt nbsp资格 认证考试 nbsp gt nbsp计算机等级考试 计算机三级网络技术分类练习题 网络基本概念 一 doc6页 本文档一共被下载 次 您可全文免费在线阅读后下载本文档 下载提
  • 高可用集群(1)- Pacemaker+Corosync实现负载均衡和高可用

    1 问题引入 计算机集群可用于提供高可用性服务或资源 多台机器的冗余是用来防止多种类型的故障 集群将使用Pacemaker和Corosync提供资源管理和消息传递 下面将介绍所需的包和对其配置文件的修改 以及使用Pacemaker命令行工具
  • 循环的断点调试,指定第几次循环

    循环的断点调试 指定第几次循环 右击断点添加条件 断点要设置在条件之后 例如本次 想要i 3的时候的循环 条件要设到i后边 令i 3 回车 再按F5即可
  • CSS 学习笔记(基础)

    用来控制网页表现的语言 CSS Cascading Style Sheet 层叠样式表 然后我们继续看看 W3C 标准 结构 HTML 表现 CSS 行为 JavaScript CSS导入方式 选择器 属性 由于网页的框架结构是由HTML实
  • pydantic学习与使用 ------ 基本模型(BaseModel)使用

    前言 在 pydantic 中定义对象的主要方法是通过模型 模型继承 BaseModel pydantic主要是一个解析库 而不是验证库 验证是达到目的的一种手段 建立一个符合所提供的类型和约束的模型 换句话说 pydantic保证输出模型
  • Google FlatBuffers——开源、跨平台的新一代序列化工具

    前段时间刚试用了一个序列化工具cereal 请看 cereal C 实现的开源序列化库 打算再总结下我对google proto buf序列化库的使用呢 结果还没动手 大Google又出了一个新的 开源 跨平台的序列化工具 FlatBuff