欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > flatbuffer实践

flatbuffer实践

2025/5/15 5:51:32 来源:https://blog.csdn.net/xiaoyaolangwj/article/details/147786972  浏览:    关键词:flatbuffer实践

FlatBuffer:面向速度的高效序列化库

一、理论

FlatBuffer是一种由Google开发的开源序列化库,针对游戏开发和其他高性能需求场景。它允许在不解码或不分配内存的情况下直接访问序列化数据,极大提高了读取速度。

该库采用预定义的数据模型结构(schema),以二进制形式存储数据,通过指针直接访问,减少了解析时间和内存开销。使用FlatBuffer时,需编写Schema文件并利用编译器生成接口代码。它支持向后兼容性,适用于快速加载和处理数据的应用程序,如游戏和网络通信。FlatBuffer源代码、示例、文档和编译器通常包含在提供的压缩包中,便于开发者理解和实现。

  • 序列化是将结构化的数据转换为二进制格式的过程,以便于在网络传输或存储。
    • FlatBuffer通过扁平化的数据结构,
    • 减少了序列化过程中的内存分配和复制操作,
    • 从而大幅提高了序列化效率。
    • 可以执行“零拷贝”序列化(Zero-copy serialization)
  • 反序列化是序列化的逆过程,即将二进制数据还原为内存中的数据结构。
    • FlatBuffer序列化后的数据中直接包含了数据结构的信息,
    • ​​​​​​​直接通过偏移量读取数据。

FlatBuffer支持在内存中直接修改数据对象,而不需要对数据进行复制。此外,FlatBuffer还支持零拷贝读取,这意味着从网络或磁盘读取数据时,可以不必将其拷贝到内部缓冲区,而是直接访问原始数据。这一策略对于提高系统的整体性能和吞吐量至关重要。

3.2 二进制文件存储的优势
3.2.1 二进制与文本格式对比分析
二进制格式与传统的文本格式(例如JSON或XML)相比较,在空间和时间效率上通常有显著优势:

  • 空间效率 :二进制格式不包含任何不必要的空白字符或标记,可以实现更紧凑的数据表示。例如,一个整数在文本格式中可能需要4到5个字节来表示,但在二进制格式中可能只占用4个字节。
  • 时间效率 :读写二进制数据通常比处理文本数据快,因为不需要解析多余的标记和空白字符。

然而,二进制格式的缺点是可读性较差,调试和错误跟踪可能更为困难。此外,二进制格式也缺乏灵活性,因为对数据模型的任何改动都需要在客户端和服务端之间进行协调。


二、预定义结构schema与二进制存储

3.1.1 schema的结构与功能
FlatBuffer的schema定义了一套固定格式,它类似于其他序列化库使用的接口描述语言(IDL)。然而,它比IDL更加紧凑,因为它不描述方法或服务,而仅专注于数据结构本身。schema的结构通常由一系列的枚举(enum)、表(table)、结构体(struct)以及它们之间的关系组成。

  • 枚举(enum):用于定义一组命名的整数常量。在schema中定义枚举,可以简化数据的表示,因为枚举值能够直接被序列化和反序列化,而不需要额外的映射或查找表。
  • 表(table):可以包含多个字段,这些字段可以是其他表、结构体、基本数据类型或枚举。表的一个重要特点是它支持字段的可选性,这意味着不是所有的字段都需要被填充。这一点与传统的C结构体不同,在传统结构体中,每个字段都需要被分配空间。
  • 结构体(struct):与表类似,但所有字段都是必需的。由于其紧凑性,struct常用于二进制通信协议中,因为它们可以高效地序列化和反序列化,不需要处理空值。
// schema定义
namespace example;enum Color { RED, GREEN, BLUE };table Monster {pos: Vec3;mana: int;hp: int (deprecated);color: Color (required);name: string;inventory: [int];
}


深入浅出 FlatBuffers 之 Schema

深入浅出 FlatBuffers 之 Schema

FlatBuffers 的主要目标是避免反序列化。这是通过定义二进制数据协议来实现的,一种将定义好的将数据转换为二进制数据的方法。

由该协议创建的二进制结构可以 wire 发送,并且无需进一步处理即可读取。相比较而言,在传输 JSON 时,我们需要将数据转换为字符串,通过 wire 发送,解析字符串,并将其转换为本地对象。Flatbuffers 不需要这些操作。你用二进制装入数据,发送相同的二进制文件,并直接从二进制文件读取。

FlatBuffers (9490 star) 和 Cap'n Proto (5527 star)、simple-binary-encoding (1351 star) 一样,它支持“零拷贝”反序列化,在序列化过程中没有临时对象产生没有额外的内存分配,访问序列化数据也不需要先将其复制到内存的单独部分,这使得以这些格式访问数据比需要格式的数据(如JSON,CSV 和 protobuf)快得多。

Unions 是一种能够在一个 FlatBuffer 中发送多种消息类型的好方法。请注意,因为union 字段实际上是两个字段(有一个隐藏字段),所以它必须始终是表的一部分,它本身不能作为 FlatBuffer 的 root。

  • id:n (on a table field)
    id 代表设置某个字段的标识符为 n 。一旦启用了这个 id 标识符,那么所有字段都必须使用 id 标识,并且 id 必须是从 0 开始的连续数字。需要特殊注意的是 Union,由于 Union 是由 2 个字段构成的,并且隐藏字段是排在 union 字段的前面。(假设在 union 前面字段的 id 排到了6,那么 union 将会占据 7 和 8 这两个 id 编号,7 是隐藏字段,8 是 union 字段)添加了 id 标识符以后,字段在 schema 内部的相互顺序就不重要了。新字段用的 id 必须是紧接着的下一个可用的 id(id 不能跳,必须是连续的)。

FlatBuffers 命名规范

schema 中的标识符是为了翻译成许多不同的编程语言,所以把 schema 的编码风格改成和当前项目语言使用的风格,是一种错误的做法。应该让 schema 的代码风格更加通用。

  • Table, struct, enum and rpc names (types) 采用大写驼峰命名法。
  • Table and struct field names 采用下划线命名法。这样做方法自动生成小写驼峰命名的代码。
  • Enum values 采用大写驼峰命名法。
  • namespaces 采用大写驼峰命名法。

还有 2 条关于书写格式的建议:

  • 大括号:与声明的开头位于同一行。
  • 间距:缩进2个空格。:两边没有空格,=两边各一个空格。

深入浅出 FlatBuffers 之 Encode

通过一篇文章认识一个人:GitHub - halfrost/Halfrost-Field: ✍🏻 这里是写博客的地方 —— Halfrost-Field 冰霜之地

这个人写的东西很有水平,有自己的网站,有自己的github,有13.1K的stars(2025年5月)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词