序列化:ProtoBuf与JSON的比较
介绍
同类
原理
ProtoBuf编译器安装
举个例子
1.先创建一个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项目
3. 编译proto文件至Java版本
src/main
目录下
protoc --java_out=./java ./proto/*.proto
src/main/java
里已经生成里对应的Java类
4. 依赖Java版本的ProtoBuf支持库
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());
ListphoneList = personOut.getPhoneList();
for (Message.Person.Phone phone : phoneList)
{
System.out.printf( "手机号:%s (%s)\n", phone.getNumber(), phone.getType());
}
比较
比较结果结果
【 JSON 开始编码 】
JSON 编码1次,耗时:22ms
JSON 数据长度:106
-开始解码-
JSON 解码1次,耗时:1ms
【 ProtoBuf 开始编码 】
ProtoBuf 编码1次,耗时:32ms
ProtoBuf 数据长度:34
-开始解码-
ProtoBuf 解码1次,耗时:3ms
【 JSON 开始编码 】
JSON 编码10次,耗时:22ms
JSON 数据长度:106
-开始解码-
JSON 解码10次,耗时:4ms
【 ProtoBuf 开始编码 】
ProtoBuf 编码10次,耗时:29ms
ProtoBuf 数据长度:34
-开始解码-
ProtoBuf 解码10次,耗时:3ms
【 JSON 开始编码 】
JSON 编码100次,耗时:32ms
JSON 数据长度:106
-开始解码-
JSON 解码100次,耗时:8ms
【 ProtoBuf 开始编码 】
ProtoBuf 编码100次,耗时:31ms
ProtoBuf 数据长度:34
-开始解码-
ProtoBuf 解码100次,耗时:4ms
【 JSON 开始编码 】
JSON 编码1000次,耗时:39ms
JSON 数据长度:106
-开始解码-
JSON 解码1000次,耗时:21ms
【 ProtoBuf 开始编码 】
ProtoBuf 编码1000次,耗时:37ms
ProtoBuf 数据长度:34
-开始解码-
ProtoBuf 解码1000次,耗时:8ms
【 JSON 开始编码 】
JSON 编码10000次,耗时:126ms
JSON 数据长度:106
-开始解码-
JSON 解码10000次,耗时:93ms
【 ProtoBuf 开始编码 】
ProtoBuf 编码10000次,耗时:49ms
ProtoBuf 数据长度:34
-开始解码-
ProtoBuf 解码10000次,耗时:23ms
【 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的性能。
内存占用
结尾
兼容
新增字段
-
在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)
开发者全社区
评论