序列化:ProtoBuf與JSON的比較
介紹
同類
原理
ProtoBuf編譯器安裝
舉個(gè)例子
1.先創(chuàng)建一個(gè)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. 創(chuàng)建一個(gè)Java項(xiàng)目
3. 編譯proto文件至Java版本
src/main 目錄下
protoc --java_out=./java ./proto/*.proto
src/main/java 里已經(jīng)生成里對(duì)應(yīng)的Java類
4. 依賴Java版本的ProtoBuf支持庫(kù)
implementation 'com.google.protobuf:protobuf-java:3.9.1'
5. 將Java對(duì)象轉(zhuǎn)為ProtoBuf數(shù)據(jù)
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 編碼耗時(shí):" + (System.currentTimeMillis() - old));
System.out.println(Arrays.toString(buff));
System.out.println("ProtoBuf 數(shù)據(jù)長(zhǎng)度:" + buff.length);
6. 將ProtoBuf數(shù)據(jù),轉(zhuǎn)換回Java對(duì)象
System.out.println("-開(kāi)始解碼-");
old = System.currentTimeMillis();
Message.Person personOut = Message.Person.parseFrom(buff);
System.out.println("ProtoBuf 解碼耗時(shí):" + (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( "手機(jī)號(hào):%s (%s)\n", phone.getNumber(), phone.getType());
}
比較
比較結(jié)果結(jié)果
【 JSON 開(kāi)始編碼 】
JSON 編碼1次,耗時(shí):22ms
JSON 數(shù)據(jù)長(zhǎng)度:106
-開(kāi)始解碼-
JSON 解碼1次,耗時(shí):1ms
【 ProtoBuf 開(kāi)始編碼 】
ProtoBuf 編碼1次,耗時(shí):32ms
ProtoBuf 數(shù)據(jù)長(zhǎng)度:34
-開(kāi)始解碼-
ProtoBuf 解碼1次,耗時(shí):3ms
【 JSON 開(kāi)始編碼 】
JSON 編碼10次,耗時(shí):22ms
JSON 數(shù)據(jù)長(zhǎng)度:106
-開(kāi)始解碼-
JSON 解碼10次,耗時(shí):4ms
【 ProtoBuf 開(kāi)始編碼 】
ProtoBuf 編碼10次,耗時(shí):29ms
ProtoBuf 數(shù)據(jù)長(zhǎng)度:34
-開(kāi)始解碼-
ProtoBuf 解碼10次,耗時(shí):3ms
【 JSON 開(kāi)始編碼 】
JSON 編碼100次,耗時(shí):32ms
JSON 數(shù)據(jù)長(zhǎng)度:106
-開(kāi)始解碼-
JSON 解碼100次,耗時(shí):8ms
【 ProtoBuf 開(kāi)始編碼 】
ProtoBuf 編碼100次,耗時(shí):31ms
ProtoBuf 數(shù)據(jù)長(zhǎng)度:34
-開(kāi)始解碼-
ProtoBuf 解碼100次,耗時(shí):4ms
【 JSON 開(kāi)始編碼 】
JSON 編碼1000次,耗時(shí):39ms
JSON 數(shù)據(jù)長(zhǎng)度:106
-開(kāi)始解碼-
JSON 解碼1000次,耗時(shí):21ms
【 ProtoBuf 開(kāi)始編碼 】
ProtoBuf 編碼1000次,耗時(shí):37ms
ProtoBuf 數(shù)據(jù)長(zhǎng)度:34
-開(kāi)始解碼-
ProtoBuf 解碼1000次,耗時(shí):8ms
【 JSON 開(kāi)始編碼 】
JSON 編碼10000次,耗時(shí):126ms
JSON 數(shù)據(jù)長(zhǎng)度:106
-開(kāi)始解碼-
JSON 解碼10000次,耗時(shí):93ms
【 ProtoBuf 開(kāi)始編碼 】
ProtoBuf 編碼10000次,耗時(shí):49ms
ProtoBuf 數(shù)據(jù)長(zhǎng)度:34
-開(kāi)始解碼-
ProtoBuf 解碼10000次,耗時(shí):23ms
【 JSON 開(kāi)始編碼 】
JSON 編碼100000次,耗時(shí):248ms
JSON 數(shù)據(jù)長(zhǎng)度:106
-開(kāi)始解碼-
JSON 解碼100000次,耗時(shí):180ms
【 ProtoBuf 開(kāi)始編碼 】
ProtoBuf 編碼100000次,耗時(shí):51ms
ProtoBuf 數(shù)據(jù)長(zhǎng)度:34
-開(kāi)始解碼-
ProtoBuf 解碼100000次,耗時(shí):58ms
總結(jié)
編解碼性能
-
次數(shù)在1千以下,ProtoBuf 的編碼與解碼性能,都與JSON不相上下,甚至還有比JSON差的趨勢(shì)。
-
次數(shù)在2千以上,ProtoBuf的編碼解碼性能,都比JSON高出很多。
-
次數(shù)在10萬(wàn)以上,ProtoBuf的編解碼性能就很明顯了,遠(yuǎn)遠(yuǎn)高出JSON的性能。
內(nèi)存占用
結(jié)尾
兼容
新增字段
-
在proto文件中新增 nickname 字段
-
生成Java文件
-
用老proto字節(jié)數(shù)組數(shù)據(jù),轉(zhuǎn)換成對(duì)象
Id:1994, Name:XIAOLEI
手機(jī)號(hào):100860 (HOME)
手機(jī)號(hào):100100 (MOBILE)
getNickname=
刪除字段
-
在proto文件中刪除 name 字段
-
生成Java文件
-
用老proto字節(jié)數(shù)組數(shù)據(jù),轉(zhuǎn)換成對(duì)象
Id:1994, Name:null
手機(jī)號(hào):100860 (HOME)
手機(jī)號(hào):100100 (MOBILE)
開(kāi)發(fā)者全社區(qū)
評(píng)論
圖片
表情
