移动场景下通信协议FlatBuffers、ProtocolBuffers、MessagePack选优

本文引用:https://www.jianshu.com/p/987c4d16c48b?from=timeline&isappinstalled=0

https://blog.csdn.net/sb___itfk/article/details/105638858


大家都知道JSON是纯文本协议,优点是可读性高,使用简单方便;而正是它的优点造成了它解析费时、解析内存耗费高、及数据量大的问题。在移动场景对性能要求极高的情况下,选择JSON作为通信协议无疑不是最佳。为了解决上述问题,特对MessagePack、FlatBuffer、ProtocolBuffers这几种当下流行的通信协议进行了学习研究,与JSON相对比,综合不同场景分析协议的优劣之处。

首先简单介绍一下几种协议的基本原理及其用法。

FlatBuffers,可参见FlatBuffers在android的使用简介android FlatBuffers剖析

MessagePack,参见MessagePack简介及使用

ProtoBuf,参见ProtocolBuffers的编码Android Studio使用ProtocolBuffers

网上有很多对这几种数据协议的对比和评论,但大都范范的给出FB更好或者是PB更优的结论,我想说这是很不严谨的,不同的数据格式、真实数据的内容、数据的复杂度等都影响了几种协议的对比效果。而实际使用场景中也必须从序列化反序列化速度、内存耗费、使用成本等方面综合考虑。

下面就从几大方面选取不同数据样本进行分析对比,希望能给大家一个参考。

第一种对比方式,改变样本量大小看对比结果

样本1数据样式

{"error_no":0,"message":"","result":{"data":[{"datatype":1,"itemdata":{//共有字段45个"sname":"\u5fae\u533b","packageid":"330611",…"tabs":[{"type":1,"f":"abc"},…]}},…],"hasNextPage":true,"dirtag":"soft"}}

测试方式

通过填充data的数据个数来扩大样本容量,选取JSON格式下的6K(data数据=1)、30K(data数据=7)、60K(data数据=15)、600K(data数据=154)、6000K(data数据=1540)、12000K(data数据=3080)为样本。

从客户端角度,对比以下四方面:序列化后原始数据大小、反序列化耗时、反序列化耗内存大小。结果对比主要选择6K、30K、60K、600K、6000K的测试结果进行。

测试结论

1. 序列化后数据大小对比

相同的数据内容用不同格式编码,进行存储后的文件大小数据如下表:

序列化数据压缩对比图

按照节省的空间从大到小排序:msgpack> pb>fb>json。由于该数据样本中基本数据类型(int,float等)较少,因此pb对基本数据类型进一步zigzag编码的优势没有充分体现,但与msgpack数据相差不大。

排名:msgpack> pb>fb

2. 反序列化耗内存大小对比

相同的数据内容按不同格式编码后,读取到内存中,进行反序列化操作,查看占用的内存情况

反序列化耗费内存大小对比.png

反序列化耗费内存从大到小排序msgpack>json>pb>fb,msgpack耗费内存约为json的1.6倍,fb、pb耗费内存差别不大。

排名:fb>pb >msgpack

3. 反序列化耗时

将序列化后的数据读取到内存后,开始计算反序列化成完整java对象的时间

在解析耗时方面这几种数据格式都优于json,排名:pb>msgpack>fb。

4. 该对比方式下的结论:

在反序列化耗内存大小方面,msgpack远远超出json(1.6倍),由于内存是移动客户端场景下的重要指标,因此基本可以排除msgpack。

只看pb和fb的排名:

序列化后大小:pb>fb

反序列化耗内存: fb>pb

反序列化耗时:pb>fb

综合来看pb更优

第二种对比方式:考虑层级对结论的影响

排除了msgpack后,我们对pb和fb进行进一步分析,考虑样本对对比结果的影响,选取两种样本:

样本选取

样本2将层级内数据减少到最小

{"error_no":0,"message":"","result":{"data":[{"datatype":1,"itemdata":{"sname":"微信","tabs":[{"type":1}]}},……],}}

样本3层级为0,数据个数多

{//共有字段45个"sname":"微信","packageid":"330611",…}

测试方式

选取样本2、样本3序列化后的数据分别进行1000次反序列化,对比总耗时和总耗费内存

测试结论

1. 序列化后数据大小对比

样本类型FB(kb)PB(kb)

样本20.210.06

样本34.083.65

pb比fb序列化后更省空间,这个结论与上面结论相同,可见PB在不同样本下序列化后的内存大小更佳。

2. 反序列化耗内存大小对比

样本类型FB(kb)PB(kb)

样本21086943

样本3765011160

数据量较大时FB比PB解析更省内存,层级较深时PB更省内存。

3. 反序列化耗时对比

样本类型FB(ms)PB(ms)

样本2415546

样本31614991

可见,当数据样式层级及结构复杂度较高,而层级内数据量不大时,反序列化耗时FB更有优势,但两者差别不大,当层级内数据量较大时,PB更省时间。

进一步结论,干货时间!!!

在序列化后的存储空间占用方面,PB绝对优于FB,假设样本中数字较多时,PB的优势将更明显,因为zigzag的编码让数字变得更省空间。

在解析耗时方面,PB更优。虽然当数据层级较深而层级内数据量较小时,FB更有优势,而一旦层级内数据量变大,则PB会更省时间。为什么PB在这种场景下更快呢?分析这可能与FB的寻址方式有关,每个变量的读取都需要先去vtable查询偏移量,再根据偏移量移动指针读取数据,而偏移量都是基于vtable基准点计算得出的,每次读取都需要从基准点处重新寻址,而且读取过程没有顺序可言,当层级内数据较多时全部读取完毕需要更长时间。而PB不需要这么复杂的过程,直接顺序读取完毕,按k-v的对应关系赋值给相应变量即可。因此,FB更适合存储大块二进制数据,比如图片、游戏数据等;PB更适合短而复杂的通信协议。

在解析耗内存方面,FB比PB更优。这也是由存储方式以及协议的复杂度决定的,FB在访问数据时不需要创建临时内存,每个数据的存储位置可以认为是指定好的,直接读取内存就可实现反序列化,不需要复杂的解析逻辑,因此省去了很多中间对象的创建、内存申请;而PB是K-V存储方式,每个数据存放的先后顺序及位置是不能预知的,因此需要遍历过程去完成数据的解析,然后包装对应到对象,比FB多了解析过程。

实际传输场景下的选优

笔者项目目前的通信协议基本为样式1所示数据格式,按分析结论选择PB为最佳,但在实际通信场景中是否如此呢,为此做了进一步验证。

测试方式

一次传输过程中数据传输前压缩(Gzip)和不压缩两种情况下,对比客户端总内存消耗和传输流量降低、传输耗时几方面。

基于样本1数据,取PB、FB与JSON进行对比。样本数据60K(Json格式下)。

1. 内存开销及传输流量对比

协议及压缩方式原始数据序列化压缩后大小传输大小解压用内存反序列化内存客户端总内存耗费内存开销降低传输流量降低

JSON+gzip606014.2214.22200.41473687.63无无

PB+gzip603313.4113.41167.65133314.0654%6%

PB6033无33013316676%-132%

FB+gzip6038.1215.1215.12184.02130329.1452%-6%

FB6038.12无38.120130168.1276%-168%

结论:

不采用GZIP压缩直接进行二进制传输对内存开销降低影响明显,但反面影响是传输流量会增长1.3到1.7倍不等。考虑非WIFI用户的流量成本,建议仍然使用GZIP压缩的方式。

FB+GZIP的传输流量JSON+GZIP方式还要多,且总内存耗费要高于PB+GZIP

因此选择PB+GZIP。

2. 整体耗时

一次传输完成耗时=通信耗时+解压缩耗时+反序列化耗时,由于压缩后的数据大小相差并不明显,因此同是GZIP压缩后再传输对通信时间的影响可忽略不计。因此数据从传输开始到解析完成的耗时只受解压缩耗时和反序列化耗时两方面影响。

对比几种数据解压缩耗时结果如下表

Data个数JSONFBPB

152.42.71.9

15419.322.216

1540173.9180.8157.8

3080327.4304.6237.9

结论:

可见不同数据格式压缩后的解压耗时时间差别不大,优劣排名PB>FB。

而反序列化耗时方面PB>FB,因此采用PB+GZIP优于FB+GZIP

结论

验证结果表明,选择PB更适合,传输前仍然需要GZIP压缩。

集成成本

分析了协议本身的优劣,我们再来看一下不同协议的使用成本。

1. android端几种方式的jar包大小对比

协议jar大小(kb)

msgpack114

pb-lite241

fb11

2. 集成难度对比

Msgpack

优势:无需编译java文件

缺点:解析需要自己写,没有封装类,序列化和反序列化需要严格对齐格式及顺序,容易出错;另外空字段需要占位;数据结构有嵌套时使用Extension封装较麻烦。还有其他的问题还未验证到。

Fb&pb

优势:解析工作已经在编译生成的类中完成,只需要序列化工作;序列化时各字段顺序不必按指定顺序,也可不填写某些字段;两端只需维护一个schema文件即可。

缺点

需编译,先编写schema再编译成各平台语言。有一定的维护成本。

数据和对象样式有强关联,用起来不是很灵活,比较适合数据协议固定且数据量大的通信场景。

编译后的java类注释丢失,代码可读性较差

测试复杂度提高

fb的使用比pb更麻烦一点,多了一步数据索引的创建。

Json

优点:数据透明,使用方便,测试成本低

缺点:不安全,解析耗时,内存耗费高

几句话总结

选择哪种通信协议要根据自己的场景结合不同协议的特性综合考虑,没有一种绝对最优的协议,只有最合适的

除了协议本身的优劣之外,还需要综合考虑集成成本、对包大小影响等因素。

最后,最重要的,关键要看想要解决的问题是什么。如果从使用成本,方便性上选择,那json是最佳,那就要牺牲内存和时间。如果从解析速度上考虑,那就要降低对包大小等方面的要求。

作者:爱唱歌的王小猫

链接:https://www.jianshu.com/p/987c4d16c48b

来源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容