Protocol Buffers是Google跨语言、跨平台的通用序列化库。FlatBuffers同样出自Google,而且也跨语言跨平台,但更强调效率,专门为游戏开发打造。在游戏界混了几年,各种各样的序列化协议都见过,MUD的字符串、Json、二进制、Protocol Buffers,各有各的优缺点。

  Protocol Buffers采用的是单个字段压缩到数组的方式。例如:

message CPing
{
int32 x = 1;
int32 y = 2;
int32 z = 3;
int32 way = 4;
}

则字段x的索引为1,y的索引为2,依此类推,最终经过Protocol Buffers把索引、数据都压缩后,在内存中大概是这样排列的:

  FlatBuffers则采用内存映射的方式,例如:

table CPing
{
x:int;
y:string;
}

参考C结构体在内存中的结构模型,像int这种内存不变的,称为POD类型,无法预先知道长度的(比如字符串),称为指针类型。FlatBuffers直接把内存中结构体类型直接搬到了序列化内存中。header总是在最前端,记录了各个成员的位置。各个成员的位置如果是POD类型,则记录数据,如果是指针类型,则记录数据位置。然后通过严格的内存对齐参数,用编译器实现跨语言、跨平台。大概是这样:

  Protocol Buffers和FlatBuffers具体的序列化、反序列化还有很多细节,比如压缩算法、内存如何对齐,这里难以详细说明,有兴趣可以自己去查资料。

  我自己业余实现了一个服务器框架,以C++为底层,Lua作为上层逻辑脚本。为了提高开发效率,所有消息到达脚本时都会自动序列化为Lua的table,不需要开发人员去解析数据包。例如:

message CPing
{
int32 x = 1;
int32 y = 2;
int32 z = 3;
int32 way = 4;
}

到达脚本时,就会是一个table,如:

{
x = ,
y = ,
z = ,
way = ,
}

所使用的库为:

Protocol Buffers:https://github.com/cloudwu/pbc

Flatbuffers:https://github.com/changnet/lua_flatbuffers

现在为了测试打包、解包效率,设计了这么一个流程:

玩家actor的数据包先经过网关gateway,再由网关转发给游戏世界world。然后world会返回数据给gateway,再转发给actor。开启4个进程,每个进程登录2500个玩家,每个玩家1000个数据包,每秒发送8个,所以最快是1000 / 8 = 125秒。系统为ubuntu 14.04,Docker版本 17.03.1-ce, build c6d412e ,程序编译参数为-g0 -O2,所有进程运行在同一Docker中,机器配置为hp probook 4446(cpu为A8-4500m):

CPU MHz:               1400.000
BogoMIPS: 3792.91
Virtualization: AMD-V
L1d cache: 16K
L1i cache: 64K
L2 cache: 2048K
NUMA node0 CPU(s): 0-3

数据包为:

// 玩家发包
message CPing
{
int32 x = 1;
int32 y = 2;
int32 z = 3;
int32 way = 4;
} // 服务器回包
message SPing
{
int32 time = 1;
}

Protocol Buffers的成绩为:

FlatBuffers的成绩为:

可以看到,两个库的效率相差无几(其实因为发的数据包太简单,完全看不出来),但是Protocol Buffer的world进程使用的cpu较高,而gateway较低,说明打包消耗了更多的cpu和时间,但是转发时流量小,IO更低。而FlatBuffers则反过来了。

  上面测试的例子比较简单,都没有数组和字符串,在发送的数据加上数组和字符串:

message CPing
{
int32 x = 1;
int32 y = 2;
int32 z = 3;
int32 way = 4;
repeated int32 target = 5;
string say = 6;
}

发送的时候,数组固定为:{ 1,2,3,4,5,6,7,8,9 }而字符串固定为:"android ping test android ping test android ping test android ping test android ping test"。同时玩家的数量减为5000,进程改为个,依然是每个进程2500个玩家。

Protocol Buffers成绩:

FlatBuffers成绩为:

可以看到,加上数组和字符串后,FlatBuffers消耗的cpu资源远小于ProtocolBuffers,但是效率上的差距因为测试的方法不当则看不出来。

  看到这里,大家可能很不理解我测试的方式,cpu基本没有跑满过。首先,我没办法让cpu刚好跑满,因为玩家那个进程是采用定时发包的方式来模拟玩家操作而不是echo方式(收到回包后再发包),所以多个玩家进程怼一个服务器进程,只要gateway和world进程有一个吃不消,就会造成数据包堆积。其次,我做这个测试是为了证明这两个库集成到我的框架中后能否达到我期望的效率。再着,这个测试中Lua的gc消耗可能是影响最大的一个因素。所以,这里只是一个参考,如果你要单纯测试这两个库的效率,可以直接测试那两个库(网上已经有不少结果了)。

  FlatBuffers的效率要高一些,而Protocol Buffers的流量要小一些,而且Protocol Buffers的使用更加广泛、成熟。项目中使用哪个,就要看个人取舍。其实,我最早写了一个二进制序列化的库,使用Json作为schema文件,也能达到自动打包、解包的效果。但是不能实现版本向后兼容,也不能实现字段冗余,不过效率比这两个都要高。后来我嫌弃自己代码写得烂,就从框架分离出去了,等有时间再整理成一个独立的库,放在https://github.com/changnet/lua_stream

  测试框架代码在https://github.com/changnet/MServer,是一个半成品,一直在忙其他的,没空完善。

Protocol Buffers与FlatBuffers效率对比的更多相关文章

  1. Xml,Json,Hessian,Protocol Buffers序列化对比

    简介 这篇博客主要对Xml,Json,Hessian,Protocol Buffers的序列化和反序列化性能进行对比,Xml和Json的基本概念就不说了. Hessian:Hessian是一个轻量级的 ...

  2. 理解netty对protocol buffers的编码解码

    一,netty+protocol buffers简要说明 Netty是业界最流行的NIO框架之一优点:1)API使用简单,开发门槛低:2)功能强大,预置了多种编解码功能,支持多种主流协议:3)定制能力 ...

  3. Protocol Buffers编码详解,例子,图解

    Protocol Buffers编码详解,例子,图解 本文不是让你掌握protobuf的使用,而是以超级细致的例子的方式分析protobuf的编码设计.通过此文你可以了解protobuf的数据压缩能力 ...

  4. .net 各种序列化方式效率对比

    在服务与服务之间传输的是二进制数据,而在此之前有多种方法将数据内容进行序列化来减小数据传递大小,现针对于目前主流的几种序列化方式做了简单数据统计对比. 先做下简单介绍↓↓↓ 1.protobuf-ne ...

  5. 详解PROTOCOL BUFFERS

    1. 前言 Protocal Buffers是google推出的一种序列化协议.由于它的编码和解码的速度,已经编码后的大小控制的较好,因此它常常被用在RPC调用中,传递参数和结果.比如gRPC. Pr ...

  6. 在Android中使用Protocol Buffers(上篇)

    本文来自网易云社区. 总览 先来看一下 FlatBuffers 项目已经为我们提供了什么,而我们在将 FlatBuffers 用到我们的项目中时又需要做什么的整体流程.如下图: 在使用 FlatBuf ...

  7. 让Web API支持Protocol Buffers

    简介 现在我们Web API项目基本上都是使用的Json作为通信的格式,随着移动互联网的兴起,Web API不仅其他系统可以使用,手机端也可以使用,但是手机端也有相对特殊的地方,网络通信除了wifi, ...

  8. Protocol buffers 介绍

    Protocol buffers和mxl一样在序列化数据结构时很灵活.高效和智能,但是它的优势在于定义文件更小,读取速度更快,使用更加简单.目前protocol buffers支持C++.java和p ...

  9. C#/net 使用Protocol Buffers入门

    Protocol buffers 是一个由谷歌开发的开源的编码机制用于将结构化的数据序列化或者反序列化,被设计成语言以及平台中立,protobuff比xml更简单比json还要紧凑一些,网上有一些关于 ...

随机推荐

  1. HTML5+CSS3静态页面项目-PayPaul的总结

    学习前端有一段时间了,一直在看书上的理论知识,而实战项目却很少.师兄常说,想要知道自己的实力有多少,知识掌握了多少,最好的方法就是去实践了,实践出真知嘛.于是决定在这个假期里,主要是通过项目的实践以及 ...

  2. zend framework 1 安装教程

    网上的安装教程总是一笔带过,本人结合已经爬过的坑,为大家展示最简单的安装方式: 博主环境如下: 操作系统:win7 64bit 开发环境:lnmp(phpstudy) 注意: zftest:官方下载的 ...

  3. date时间转换

    <!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/h ...

  4. python自动化运维学习第一天--day1

    学习python自动化运维第一天自己总结的作业 所使用到知识:json模块,用于数据转化sys.exit 用于中断循环退出程序字符串格式化.format字典.文件打开读写with open(file, ...

  5. WebAssembly:随风潜入夜

    What? WebAssembly 是一种二进制格式的类汇编代码,可以被浏览器加载和并进一步编译成可执行的机器码,从而在客户端运行.它还可以作为高级语言的编译目标,理论上任何语言都可以编译为 WebA ...

  6. Linux 重启和关机命令

    shutdown -r  05:30   在凌晨五点30分关机     shutdown -r  05:30 &     后台执行     shutdown -c    取消前一个关机命令   ...

  7. [基础架构]PeopleSoft工作原理(从浏览器发送请求开始)

    PeopleSoft体系结构是由几大组成部分构成,之前文章已经详细讲过,了解这几大组成部分是怎么协同工作的更为重要.在本文中将帮助您了解PeopleSoft的工作原理以及用户发送的请求是如何被解析以及 ...

  8. iOS是最安全的?苹果iOS恶意软件数量增速首次超过Android

    之前小编还说Android系统似乎已经成为世界各地病毒作者的首选目标,但是近日一份安全研究报告让小编啪啪打脸. Skycure的移动安全报告显示,近三个季度内,在iOS上运行的恶意软件增加了2倍多,而 ...

  9. Angularjs Material

    公司用Angularjs Material进行开发,之前在网站上看了一些Demo,做一个学习的整理. 1.新建窗体的数据绑定 1.1修改kendo表格新增页面按钮,添加按钮,并Dialog一个窗体 t ...

  10. nyoj_14:会场安排问题

    一道很经典的贪心问题 题目链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=14 #include<iostream> #inclu ...