尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

FlatBuffers 概览:零解析、内存高效的跨平台序列化库

FlatBuffers 概览:零解析、内存高效的跨平台序列化库 FlatBuffers 概览零解析、内存高效的跨平台序列化库【免费下载链接】flatbuffersFlatBuffers: Memory Efficient Serialization Library项目地址: https://gitcode.com/GitHub_Trending/fl/flatbuffersFlatBuffers 是 Google 为游戏开发及性能敏感场景设计的跨平台序列化库支持 C、C#、Java、Kotlin、Go、Rust、Python、TypeScript、Swift 等十余种语言。本篇文章以官方文档 Overview 为骨架结合仓库内的源码、示例与编译器文档系统讲解其核心设计理念、四大优势的底层实现依据以及从 schema 编写到代码生成的完整上手流程帮助你判断它是否适合你的数据交换场景。FlatBuffers 是什么FlatBuffers 是一种内存高效Memory Efficient的跨平台序列化库官方文档给出的支持语言包括 C、C#、C、Go、Java、Kotlin、JavaScript、Lobster、Lua、TypeScript、PHP、Python、Rust 与 SwiftNim 也已加入见 README.md 的语言列表。它最初由 Google 为游戏开发及其他性能关键型应用而创建以 Apache License v2.0 开源。与传统的先序列化成二进制、读取时再解析成内存对象的序列化方案不同FlatBuffers 采用**直接内存访问zero-copy**的二进制布局序列化后的 buffer 本身就是可被直接读取的数据结构。这一点贯穿整个库的设计也是理解它全部特性的钥匙。为什么选择 FlatBuffers四大核心优势官方 Overview 用四个关键词概括了它的核心价值以下结合仓库源码逐一展开。1. 无需解析/解包即可访问序列化数据这是 FlatBuffers 最独特的卖点。官方文档原文为Access the data directly without unpacking or parsing.直接访问数据无需解包或解析。传统方案如 Protocol Buffers、JSON读取数据时需要先反序列化到一组内存对象再通过对象访问字段而 FlatBuffers 生成的访问器accessor直接对原始 buffer 做偏移计算后读取。这一点可以在 samples/sample_binary.cpp 中看到实证序列化完成后GetMonster(builder.GetBufferPointer())直接返回指向 buffer 内数据的访问器随后monster-hp()、monster-name()-str()、weps-Get(i)-damage()等调用全部直接在原始字节上进行没有任何中间对象分配。2. 内存效率与速度官方文档指出The only memory needed to access your data is that of the buffer. No heap is required.访问数据所需的内存只有 buffer 本身无需堆分配。这一特性由 FlatBuffers 的二进制格式保证标量字段按对齐规则内联存放string、vector、table 等通过偏移量offset引用读取端不产生对象拷贝。仓库文档 benchmarks.md 记录的对比数据注意该基准基于较早的测试环境用于说明设计方向而非当前环境结论显示解码 100 万次的耗时中 FlatBuffers 为 0.08 秒解码/遍历/释放分解为 0 / 0.08 / 0而 Protocol Buffers LITE 为 302 秒、Rapid JSON 为 583 秒解码后存储所需内存一栏 FlatBuffers 为 0 字节/0 块反观 Protobuf 为 760 字节/20 块、Rapid JSON 为 65689 字节/4 块。这正是无解析、无堆分配的直接量化体现。3. 前后向兼容Backwards Forwards Compatibility官方文档FlatBuffers enables the schema to evolve over time while still maintaining forwards and backwards compatibility with old flatbuffers.其实现机制在 schema.md 中有明确说明table 的字段可以随时追加也可以在声明deprecated后废弃而旧数据依然可读、新字段缺失时返回默认值。每个字段在二进制中通过 vtable 间接寻址字段是否出现是独立的——缺失字段按三种互斥方式处理返回 schema 中声明的默认值默认模式、返回nulloptional 模式如hp:short null、或触发校验失败required模式。因此添加字段不撑大数据、旧客户端读新数据、新客户端读旧数据都能成立这也是 FlatBuffers 适合长期演进协议的根本原因。4. 体积小、依赖少Small Footprint官方文档Minimal dependencies and small code footprint.极少的依赖与很小的代码体积。C 运行时只有一个头文件 include/flatbuffers/flatbuffers.hbuilding.md 明确说明对大多数使用场景没有需要编译的运行时只需把include目录加入头文件搜索路径仅当需要在运行时动态解析 schema 或做文本/二进制互转时才需要额外编译 src/idl_parser.cpp以及文本输出的 src/idl_gen_text.cpp。benchmarks 文档同样记录FlatBuffers 生成代码体积约 4 KB、库源码约 15 KB相比 Protobuf 数 MB 级别的库源码量级小得多。实战流程从 schema 到跨语言读取官方 README.md 给出六步快速上手流程这也是 tutorial.md 详细展开的主线构建编译器flatc用 CMake 生成构建文件并编译Linux 示例cmake -G Unix Makefiles然后make -j详细构建方式CMake / Bazel / Conan / vcpkg / Android见 building.md。编写 schema.fbs文件用 FlatBuffers 的 IDL 语言描述数据结构。生成目标语言代码./flatc --cpp --rust monster.fbs会生成monster_generated.h与monster_generated.rs。序列化数据使用生成代码与FlatBufferBuilder构造二进制 buffer。传输/存储 bufferbuilder.GetBufferPointer()与builder.GetSize()拿到原始字节。读取数据用生成的访问器直接读跨语言、跨 schema 版本皆可。schema 示例monster.fbs仓库 samples/monster.fbs 是一个典型的 schema 示例涵盖了 FlatBuffers 的主要类型系统namespace MyGame.Sample; enum Color:byte { Red 0, Green, Blue 2 } union Equipment { Weapon } struct Vec3 { x:float; y:float; z:float; } table Monster { pos:Vec3; mana:short 150; hp:short 100; name:string; friendly:bool false (deprecated); inventory:[ubyte]; color:Color Blue; weapons:[Weapon]; equipped:Equipment; path:[Vec3]; } table Weapon { name:string; damage:short; } root_type Monster;其中各语法要素的含义详见 tutorial.md 与 schema.mdnamespace将生成代码放入指定命名空间C 系语言完全支持enum支持指定底层整数类型的枚举未显式赋值的成员自动递增Green即 1struct纯标量字段的集合本身也是标量类型占用更少内存、查找更快但一经定义不可变更适合固定结构table可演进的主数据结构字段可增可废弃是前后向兼容的载体标量类型int8/16/32/64、uint8/16/32/64、float、double、bool全部为固定宽度不支持 varintunion一组可能类型中的单个值本质是类型枚举 值的组合root_type声明 buffer 的根对象类型。生成代码的序列化与读取以 C 为例samples/sample_binary.cpp 展示了序列化侧用builder.CreateString创建字符串、CreateWeapon快捷函数创建 table、builder.CreateVector创建向量最后builder.Finish(orc)封口根对象读取侧则如前述直接通过访问器读取标量、struct、vector 与 union 字段如monster-equipped_type()判断 union 实际类型全程无中间拷贝。同样的思路在各语言目录如 go、python、rust都有对应的运行时实现。为什么不选 Protocol Buffers官方文档指出Protocol Buffers 与 FlatBuffers 相当相似主要区别在于FlatBuffers 不需要先解析/解包到二级表示secondary representation再访问数据而这种解析往往伴随着逐对象的堆内存分配。此外Protobuf 的代码量大一个数量级an order of magnitude bigger。结合 benchmarks.md 的仓库记录可以佐证同样是解码 100 万次Protobuf LITE 耗时 302 秒 vs FlatBuffers 0.08 秒解码过程中的瞬时内存分配 Protobuf 为 1 KB 而 FlatBuffers 为 0生成源码体积 61 KB vs 4 KB。对延迟敏感 内存受限 协议长期演进的场景游戏、移动端、嵌入式、高频网络通信这种差异往往是决定性的。为什么不选 JSON官方文档对 JSON 的评价很客观它可读性极佳FlatBuffers 也把 JSON 作为可选的文本格式与 JavaScript 等动态类型语言配合非常方便但从静态类型语言序列化数据时存在明显的运行时效率缺陷由于其动态类型的序列化体系访问数据反而要写更多代码只有在系统对将要存储的数据几乎一无所知的场景下JSON 才是更优选择。FlatBuffers 实际上把要不要 JSON的选择权留给了开发者flatc既能把 JSON 转成二进制--binary也能把二进制转回 JSON--json见 flatc.md。这样既能享受二进制格式的性能又保留了 JSON 作为调试与配置载体的可读性。无 schema 场景的补充FlexBuffers值得顺带一提的是当数据确实无法用 schema 预先描述时FlatBuffers 生态还提供了配套的无模式二进制格式FlexBuffers详见 flexbuffers.md。它牺牲强类型但保留了无需解析/拷贝/对象分配即可访问的核心优势并通过对字符串的自动池化、容器位宽的自动收缩8/16/32/64 位获得紧凑编码。其 C 用法极简flexbuffers::Builder fbb; fbb.Int(13); fbb.Finish();即可产出一个仅 3 字节的 buffer读取时flexbuffers::GetRoot(buf).AsInt64()直接取值。它既可以独立使用也可以作为 FlatBuffers 某个字段的内嵌格式为schema 化为主、自由数据为辅的混合场景提供了完整方案。深入阅读指引编译器flatc的完整命令行参考所有语言生成选项、数据转换、gRPC 选项docs/source/flatc.mdschema 语言完整语法与字段行为默认/optional/required 三种缺失语义、struct 与 vector 等docs/source/schema.md分语言教程schema → 生成代码 → 序列化 → 反序列化docs/source/tutorial.md 及 docs/source/languages 下的各语言文档构建方式CMake / Bazel / Conan / vcpkg / Android与集成进自有 CMake 工程的方法docs/source/building.md完整可运行的 C 示例samples/sample_binary.cpp、schema 文件 samples/monster.fbs总结如果你的系统有明确的、可演进的数据结构且对解析开销、内存占用、跨语言互操作有较高要求FlatBuffers 的零解析直读模型能同时满足性能与兼容性而 JSON 更适合数据形态不可预知的动态场景FlexBuffers 则是介于两者之间的自由格式补充。结合本文给出的源码路径与官方文档你可以直接在本仓库中运行示例、验证其行为再决定是否引入自己的项目。【免费下载链接】flatbuffersFlatBuffers: Memory Efficient Serialization Library项目地址: https://gitcode.com/GitHub_Trending/fl/flatbuffers创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表