当前位置: 首页 > backend >正文

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月)

http://www.xdnf.cn/news/6121.html

相关文章:

  • 操作系统实验 实验3 存储器分配与回收
  • 设计模式-中介者模式
  • Docker使用经验-从Image导出dockerfile并进行修改
  • 【Elasticsearch】DSL 篇
  • 什么是alpaca 或 sharegpt 格式的数据集?
  • Windows电脑端高效记事提醒工具推荐
  • 【ios越狱包安装失败?uniapp导出ipa文件如何安装到苹果手机】苹果IOS直接安装IPA文件
  • SCDN能够运用在物联网加速当中吗?
  • Spring Web MVC————入门(2)
  • Spark处理过程--案例数据清洗
  • 大模型越狱:技术漏洞与安全挑战——从原理到防御
  • 正向代理与反向代理区别及应用
  • 威廉・巴拉德与格理集团:在高科技浪潮中的洞察与前行
  • 【极兔快递Java社招】一面复盘|数据库+线程池+AQS+中间件面面俱到
  • 【Linux网络】————详解TCP三次握手四次挥手
  • vue3:十三、分类管理-表格--slot插槽详细说明---表格内拼接字段、tag标签
  • 怎么查看当前vue项目,要求的node.js版本
  • Oracle — PL-SQL
  • JT/T 808 各版本协议字段级别对比与解析适配建议
  • NACOS基于长链接的⼀致性模型
  • 将navicat与parcharm链接
  • 2025年中国DevOps工具选型指南:主流平台能力横向对比
  • Go语言空白导入的作用与用途
  • 【SSL部署与优化​】​​如何为网站启用HTTPS:从Let‘s Encrypt免费证书到Nginx配置​​
  • 城市生命线综合管控系统解决方案-守护城市生命线安全
  • AWS CloudTrail日志跟踪启用
  • 【计算机视觉】OpenCV实战项目:GraspPicture 项目深度解析:基于图像分割的抓取点检测系统
  • 学习51单片机01(安装开发环境)
  • 机器学习基础课程-6-课程实验
  • 精益数据分析(57/126):创业移情阶段的核心要点与实践方法