还在用Protocol Buffers?快来看看FlatBuffers!

FlatBuffers 非常适合需要高性能数据传输的应用程序。它在速度、数据大小和类型安全性方面提供
首页 新闻资讯 行业资讯 还在用Protocol Buffers?快来看看FlatBuffers!

如果你正在寻找一种快速、高效的跨平台数据序列化库,FlatBuffers 绝对是一个值得探索的选择。由 Google 开发,FlatBuffers 旨在提供比其他序列化库(例如 Protocol Buffers 和 JSON)更高性能的解决方案。今天,我们将深入了解 FlatBuffers 的工作原理,通过一些代码示例展示如何使用它,并与其他常见的数据格式进行对比。

什么是 FlatBuffers?

FlatBuffers 是一个高效的、跨平台的序列化库,特别适用于游戏开发、网络通信和嵌入式系统。它具有以下几个主要特点:

  • 零拷贝反序列化:无需解析或解包即可直接访问数据。

  • 向后兼容:可以在不破坏现有数据格式的情况下扩展结构。

  • 多语言支持:支持多种编程语言,包括 C++, C#, C, Go, Java, JavaScript, PHP, Python, Rust, Swift 等。

安装 FlatBuffers

在开始之前,我们需要安装 FlatBuffers。以下是一些常见的安装方法:

使用 Homebrew(macOS)

brew install flatbuffers

使用 apt-get(Ubuntu)

sudo apt-get install flatbuffers-compiler

从源码编译

git clone https://github.com/google/flatbuffers.gitcd flatbuffers
cmake-G"Unix Makefiles"make
sudo make install

快速入门示例

让我们通过一个简单示例来看看 FlatBuffers 是如何工作的。

定义模型

首先,我们需要定义一个数据模型。假设我们有一个包含人物信息的模型:

// person.fbsnamespace MyGame.Sample;tablePerson {
id:int;name:string;age:int;email:string;}

root_type Person;

保存上述定义为 person.fbs 文件。

编译 FlatBuffers Schema

接下来,我们需要编译这个 schema 文件。这将生成用于我们应用程序的代码。

flatc--cpp person.fbs

使用 FlatBuffers 序列化和反序列化数据

现在我们已经生成了所需的代码,可以在 C++ 中使用它来序列化和反序列化数据。以下是一个简单的示例:

序列化

#include "person_generated.h"  // 自动生成的头文件#include "flatbuffers/flatbuffers.h"#include <iostream>intmain(){
 flatbuffers::FlatBufferBuilder builder;auto name=builder.CreateString("John Doe");auto email=builder.CreateString("john.doe@example.com");MyGame::Sample::PersonBuilder personBuilder(builder);personBuilder.add_id(123);personBuilder.add_name(name);personBuilder.add_age(30);personBuilder.add_email(email);auto person=personBuilder.Finish();builder.Finish(person);// 获取缓冲区指针和大小uint8_t*buf=builder.GetBufferPointer();intsize=builder.GetSize();// 将缓冲区写入文件或发送std::cout<<"Serialized data size: "<<size<<" bytes\n";return0;}

反序列化

#include "person_generated.h"#include <iostream>intmain(){// 假设 buf 和 size 是从文件或网络读取的序列化数据uint8_t*buf=...;intsize=...;auto person=MyGame::Sample::GetPerson(buf);std::cout<<"ID: "<<person->id()<<"\n";std::cout<<"Name: "<<person->name()->str()<<"\n";std::cout<<"Age: "<<person->age()<<"\n";std::cout<<"Email: "<<person->email()->str()<<"\n";return0;}

FlatBuffers 与其他数据格式的对比

让我们看看 FlatBuffers 和其他常见数据格式(如 JSON 和 Protocol Buffers)之间的主要差异。

FlatBuffers vs JSON

JSON 是一种文本格式,易于阅读和调试,广泛用于 web 应用程序。但它有几个缺点:

  • 性能:JSON 是文本格式,解析速度较慢。

  • 大小:JSON 数据通常比二进制格式大。

  • 类型安全:JSON 缺乏严格的类型约束。

FlatBuffers 的优势在于:

  • 速度:由于是二进制格式,解析和访问数据非常快。

  • 大小:二进制格式通常比 JSON 更小,占用更少的存储空间和网络带宽。

  • 类型安全:FlatBuffers 使用 schema 定义数据结构,提供了更强的类型安全性和数据验证。

FlatBuffers vs Protocol Buffers

Protocol Buffers(Protobuf)同样是由 Google 开发的序列化库,也使用二进制格式。它与 FlatBuffers 有相似之处,但也有一些关键区别:

  • 延迟:Protobuf 使用了“序列化-反序列化”的方式,这意味着数据在传输和存储时需要进行编码和解码。而 FlatBuffers 的零拷贝反序列化允许直接访问数据,减少了延迟。

  • 动态性:Protobuf 的 schema 更加灵活,可以更容易地进行字段的增加或删除。FlatBuffers 虽然也支持向后兼容,但在处理复杂的动态数据模型时可能不如 Protobuf 方便。

  • 生态系统:Protobuf 可能拥有更成熟和广泛的生态系统,特别是在 Google 内部的许多项目中都在使用。

性能对比

以下是一个简单的性能对比,可以帮助你更好地理解这些格式之间的差异:

特性

JSON

Protocol Buffers

FlatBuffers

解析速度

中等

数据大小

类型安全

序列化/反序列化

需要

需要

不需要(零拷贝)

可读性

向后兼容

较弱

较强

实践示例:FlatBuffers vs JSON

为了更直观地展示 FlatBuffers 的优势,我们来对比一下使用 FlatBuffers 和 JSON 序列化与反序列化的代码。

使用 JSON

序列化

#include <iostream>#include <nlohmann/json.hpp>usingjson=nlohmann::json;intmain(){
  json person;person["id"]=123;person["name"]="John Doe";person["age"]=30;person["email"]="john.doe@example.com";std::string serialized_data=person.dump();std::cout<<"Serialized JSON data: "<<serialized_data<<"\n";return0;}

反序列化

#include<iostream>#include<nlohmann/json.hpp>usingjson=nlohmann::json;intmain(){std::string serialized_data=R"({"id":123,"name":"John Doe","age":30,"email":"john.doe@example.com"})";autoperson=json::parse(serialized_data);std::cout<<"ID: "<<person["id"]<<"\n";std::cout<<"Name: "<<person["name"]<<"\n";std::cout<<"Age: "<<person["age"]<<"\n";std::cout<<"Email: "<<person["email"]<<"\n";return0;}

使用 FlatBuffers

上文已展示了如何在 C++ 中使用 FlatBuffers 进行序列化和反序列化。可以看到,虽然 JSON 的代码更为直观和易于调试,但 FlatBuffers 在性能和效率上具有显著优势,尤其是在处理大量数据或需要高频率数据交换的场景中。

结论

FlatBuffers 非常适合需要高性能数据传输的应用程序。它在速度、数据大小和类型安全性方面提供了显著优势,尽管学习曲线稍陡,但其性能提升和资源节省是值得的。

如果你的项目需要频繁的数据交换、高效的存储或需要在多种编程语言之间传递数据,FlatBuffers 是一个值得考虑的选择。希望这篇文章能帮助你更好地理解 FlatBuffers,并在你的项目中有效地应用它。