点击上方“方志朋”,选择“设为星标”

回复”666“获取新整理的面试文章

来源:https://my.oschina.net/xiaolei123/blog/3085607

介绍

ProtoBuf 是google团队开发的用于高效存储和读取结构化数据的工具。什么是结构化数据呢,正如字面上表达的,就是带有一定结构的数据。比如电话簿上有很多记录数据,每条记录包含姓名、ID、邮件、电话等,这种结构重复出现。

同类

XML、JSON 也可以用来存储此类结构化数据,但是使用ProtoBuf表示的数据能更加高效,并且将数据压缩得更小。

原理

ProtoBuf 是通过ProtoBuf编译器将与编程语言无关的特有的 .proto 后缀的数据结构文件编译成各个编程语言(Java,C/C++,Python)专用的类文件,然后通过Google提供的各个编程语言的支持库lib即可调用API。(关于proto结构体怎么编写,可自行查阅文档)

ProtoBuf编译器安装

Mac : brew install protobuf

举个例子

1.先创建一个proto文件

message.proto

syntax = "proto3";message Person {int32 id = 1;string name = 2;repeated Phone phone = 4;enum PhoneType {MOBILE = 0;HOME = 1;WORK = 2;}message Phone {string number = 1;PhoneType type = 2;}
}

2. 创建一个Java项目

并且将proto文件放置 src/main/proto 文件夹下

3. 编译proto文件至Java版本

用命令行 cd 到 src/main 目录下

终端执行命令 : protoc --java_out=./java ./proto/*.proto

会发现,在你的src/main/java 里已经生成里对应的Java类

4. 依赖Java版本的ProtoBuf支持库

这里只举一个用Gradle使用依赖的栗子

implementation 'com.google.protobuf:protobuf-java:3.9.1'

5. 将Java对象转为ProtoBuf数据

Message.Person.Phone.Builder phoneBuilder = Message.Person.Phone.newBuilder();
Message.Person.Phone phone1 = phoneBuilder.setNumber("100860").setType(Message.Person.PhoneType.HOME).build();
Message.Person.Phone phone2 = phoneBuilder.setNumber("100100").setType(Message.Person.PhoneType.MOBILE).build();
Message.Person.Builder personBuilder = Message.Person.newBuilder();
personBuilder.setId(1994);
personBuilder.setName("XIAOLEI");
personBuilder.addPhone(phone1);
personBuilder.addPhone(phone2);Message.Person person = personBuilder.build();
long old = System.currentTimeMillis();
byte[] buff = person.toByteArray();
System.out.println("ProtoBuf 编码耗时:" + (System.currentTimeMillis() - old));
System.out.println(Arrays.toString(buff));
System.out.println("ProtoBuf 数据长度:" + buff.length);

6. 将ProtoBuf数据,转换回Java对象

System.out.println("-开始解码-");
old = System.currentTimeMillis();
Message.Person personOut = Message.Person.parseFrom(buff);
System.out.println("ProtoBuf 解码耗时:" + (System.currentTimeMillis() - old));
System.out.printf("Id:%d, Name:%s\n", personOut.getId(), personOut.getName());
List<Message.Person.Phone> phoneList = personOut.getPhoneList();
for (Message.Person.Phone phone : phoneList)
{System.out.printf("手机号:%s (%s)\n", phone.getNumber(), phone.getType());
}

比较

为了能体现ProtoBuf的优势,我写了同样结构体的Java类,并且将Java对象转换成JSON数据,来与ProtoBuf进行比较。JSON编译库使用Google提供的GSON库,JSON的部分代码就不贴出来了,直接展示结果

比较结果结果

运行 1 次

【 JSON 开始编码 】
JSON 编码1次,耗时:22ms
JSON 数据长度:106
-开始解码-
JSON 解码1次,耗时:1ms【 ProtoBuf 开始编码 】
ProtoBuf 编码1次,耗时:32ms
ProtoBuf 数据长度:34
-开始解码-
ProtoBuf 解码1次,耗时:3ms

运行 10 次

【 JSON 开始编码 】
JSON 编码10次,耗时:22ms
JSON 数据长度:106
-开始解码-
JSON 解码10次,耗时:4ms【 ProtoBuf 开始编码 】
ProtoBuf 编码10次,耗时:29ms
ProtoBuf 数据长度:34
-开始解码-
ProtoBuf 解码10次,耗时:3ms

运行 100 次

【 JSON 开始编码 】
JSON 编码100次,耗时:32ms
JSON 数据长度:106
-开始解码-
JSON 解码100次,耗时:8ms【 ProtoBuf 开始编码 】
ProtoBuf 编码100次,耗时:31ms
ProtoBuf 数据长度:34
-开始解码-
ProtoBuf 解码100次,耗时:4ms

运行 1000 次

【 JSON 开始编码 】
JSON 编码1000次,耗时:39ms
JSON 数据长度:106
-开始解码-
JSON 解码1000次,耗时:21ms【 ProtoBuf 开始编码 】
ProtoBuf 编码1000次,耗时:37ms
ProtoBuf 数据长度:34
-开始解码-
ProtoBuf 解码1000次,耗时:8ms

运行 1万 次

【 JSON 开始编码 】
JSON 编码10000次,耗时:126ms
JSON 数据长度:106
-开始解码-
JSON 解码10000次,耗时:93ms【 ProtoBuf 开始编码 】
ProtoBuf 编码10000次,耗时:49ms
ProtoBuf 数据长度:34
-开始解码-
ProtoBuf 解码10000次,耗时:23ms

运行 10万 次

【 JSON 开始编码 】
JSON 编码100000次,耗时:248ms
JSON 数据长度:106
-开始解码-
JSON 解码100000次,耗时:180ms【 ProtoBuf 开始编码 】
ProtoBuf 编码100000次,耗时:51ms
ProtoBuf 数据长度:34
-开始解码-
ProtoBuf 解码100000次,耗时:58ms

总结

编解码性能

上述栗子只是简单的采样,实际上据我的实验发现

  • 次数在1千以下,ProtoBuf 的编码与解码性能,都与JSON不相上下,甚至还有比JSON差的趋势。

  • 次数在2千以上,ProtoBuf的编码解码性能,都比JSON高出很多。

  • 次数在10万以上,ProtoBuf的编解码性能就很明显了,远远高出JSON的性能。

内存占用

ProtoBuf的内存34,而JSON到达106 ,ProtoBuf的内存占用只有JSON的1/3.

结尾

其实这次实验有很多可待优化的地方,就算是这种粗略的测试,也能看出来ProtoBuf的优势。

兼容

新增字段

  • 在proto文件中新增 nickname 字段

  • 生成Java文件

  • 用老proto字节数组数据,转换成对象

Id:1994, Name:XIAOLEI
手机号:100860 (HOME)
手机号:100100 (MOBILE)
getNickname=

结果,是可以转换成功。

删除字段

  • 在proto文件中删除 name 字段

  • 生成Java文件

  • 用老proto字节数组数据,转换成对象

Id:1994, Name:null
手机号:100860 (HOME)
手机号:100100 (MOBILE)

结果,是可以转换成功。


你更喜欢哪种序列化方式?欢迎留言告诉肥朝。

热门内容:Spring Boot 还能“内存泄露”?排它!
学会 IDEA REST Client后,postman就可以丢掉了...
为什么老外不愿意用 MyBatis?微服务海量日志怎么处理,推荐你试试这款工具....
HTTP/3 来了 !HTTP/2 还没怎么用起来呢,先一起扫个盲吧!给 Spring Boot 项目减减肥!18.18M 到 0.18M 是如何做到的?
为什么像王者荣耀这样的游戏 Server 不愿意使用微服务?最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ♡

序列化:ProtoBuf与JSON的比较相关推荐

  1. 【java】序列化:ProtoBuf 与 JSON 的比较

    1.概述 转载:序列化:ProtoBuf 与 JSON 的比较! 介绍 ProtoBuf 是google团队开发的用于高效存储和读取结构化数据的工具.什么是结构化数据呢,正如字面上表达的,就是带有一定 ...

  2. 序列化:Protobuf 与 JSON、XML 的对比

    Protobuf .JSON.XML 的对比 XML JSON PB 数据结构支持 复杂结构 简单结构 较复杂结构 数据保存方式 文本 文本 二进制 数据保存大小 大 一般 小 解析效率 慢 一般 快 ...

  3. protobuf转json

    以字节码为交接处实现pbf和josn互转 //protobuf转json     public static void main3(String[] args) throws InvalidProto ...

  4. Java基础/利用fastjson序列化对象为JSON

    利用fastjson序列化对象为JSON 参考博客:http://blog.csdn.net/zeuskingzb/article/details/17468079 Step1:定义实体类 //用户类 ...

  5. fastjson 序列化时指定json的key值

    json字符串中的key是下划线例如:foot_dist,而实际实体类中的属性是footDist,添加 @JSONField(name = "foot_dist")即可 packa ...

  6. .Net 中关于序列化和反序列化Json的方法

    .Net SDK中关于序列化和反序列化Json的方法 项目中遇到和服务端交互时需要传递数据包为json格式的包,所以在服务端和SDK中都需要对json进行解析和组合的操作, 并且对一些复杂结构的jso ...

  7. Unity精品专栏之序列化操作之Json案例篇(上)

    1.3 Json案例:使用Unity解析上述复合JSON 前言 通过本篇博客,我会和大家通过一个案例来学习Json的操作,希望本篇博客能为大家的工作过程中带来一些帮助与启发. 若当前文章对你有所帮助, ...

  8. 二进制序列化器、XML序列化器、Json序列化器

    二进制序列化器.XML序列化器.Json序列化器 序列化是将对象的状态信息转换未可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通过从存储区读取或反序列化 ...

  9. 高效序列化protobuf和protostuff的区别

    一.前言 在我们的开发过程中,序列化是经常需要处理的问题,比如在做分布式访问数据时,或者是在做redis缓存存储数据时,如果我们涉及的知识面不够广的话,可能会简单的使用JDK的序列化,也即在需要序列化 ...

最新文章

  1. oracle打散分组函数,oracle分组函数
  2. 使用SoapUI调用不同的安全WCF SOAP服务-基本身份验证,第二部分
  3. HttpClient 学习整理(转)
  4. 差分进化算法_特邀嘉宾 | 科普差分进化算法(创新奇智运筹优化算法工程师朱小龙博士)...
  5. 逻辑运算map函数filter函数reduce函数
  6. 东北大学22春学期《概率论X》在线平时作业123
  7. 计算机程序设计流程图循环,流程图循环画法_流程图用什么办公软件
  8. 怎样保持下拉菜单截图?如何快速截图截图快捷键
  9. java设计模式学习-代理模式
  10. python 定时程序_python每天定时运行某程序代码
  11. 360校招失败的惨痛经历
  12. 联想拯救者u盘安装linux系统,联想拯救者Y7000 U盘装系统win8教程
  13. 字符串常见方法总结:方法的作用、参数、返回值
  14. 卡特兰数 Catalan数
  15. 初学媒体软件时的一些鼠绘作品
  16. 有一头母牛,它每年年初要生一头小母牛;每头小母牛从第四个年头起,每年年初也要生一头小母牛。按此规律,若无牛死亡,第20个年头上共有多少头母牛
  17. ILITEK touch driver
  18. “Let’s Eat Grandma”:标点符号(句法树)增强语义表达,用于情感分析
  19. #NOIP1999#旅行家的预算
  20. 新浪码农因加班错失年会77万特等奖,当事人称:心态崩了,想离职

热门文章

  1. 《少年先疯队》第九次团队作业:Beta冲刺第二天
  2. Bzoj1123 Blockade
  3. Isight 命令行运行任务
  4. 关于EF中批量添加的个人探索
  5. python基于Django框架编译报错“django.core.exceptions.ImproperlyConfigured”的解决办法?...
  6. ThinkPHP 3.1.2 视图 1
  7. C基础知识小总结(十)
  8. UVA 10494 - If We Were a Child Again(高精度除法和取余)
  9. 【组队学习】【31期】基于Python的办公自动化
  10. 数据结构与算法:13 字符串与整数集合