<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          序列化:ProtoBuf與JSON的比較

          共 6753字,需瀏覽 14分鐘

           ·

          2020-08-07 21:54

          來(lái)源 | oschina.net/xiaolei123/blog/3085607

          介紹

          ProtoBuf 是google團(tuán)隊(duì)開(kāi)發(fā)的用于高效存儲(chǔ)和讀取結(jié)構(gòu)化數(shù)據(jù)的工具。什么是結(jié)構(gòu)化數(shù)據(jù)呢,正如字面上表達(dá)的,就是帶有一定結(jié)構(gòu)的數(shù)據(jù)。比如電話簿上有很多記錄數(shù)據(jù),每條記錄包含姓名、ID、郵件、電話等,這種結(jié)構(gòu)重復(fù)出現(xiàn)。

          同類

          XML、JSON 也可以用來(lái)存儲(chǔ)此類結(jié)構(gòu)化數(shù)據(jù),但是使用ProtoBuf表示的數(shù)據(jù)能更加高效,并且將數(shù)據(jù)壓縮得更小。

          原理

          ProtoBuf 是通過(guò)ProtoBuf編譯器將與編程語(yǔ)言無(wú)關(guān)的特有的 .proto 后綴的數(shù)據(jù)結(jié)構(gòu)文件編譯成各個(gè)編程語(yǔ)言(Java,C/C++,Python)專用的類文件,然后通過(guò)Google提供的各個(gè)編程語(yǔ)言的支持庫(kù)lib即可調(diào)用API。(關(guān)于proto結(jié)構(gòu)體怎么編寫,可自行查閱文檔)

          ProtoBuf編譯器安裝

          Mac : brew install protobuf

          舉個(gè)例子

          1.先創(chuàng)建一個(gè)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. 創(chuàng)建一個(gè)Java項(xiàng)目

          并且將proto文件放置 src/main/proto 文件夾下

          3. 編譯proto文件至Java版本

          用命令行 cd 到 src/main 目錄下
          終端執(zhí)行命令 : protoc --java_out=./java ./proto/*.proto
          會(huì)發(fā)現(xiàn),在你的src/main/java 里已經(jīng)生成里對(duì)應(yīng)的Java類

          4. 依賴Java版本的ProtoBuf支持庫(kù)

          這里只舉一個(gè)用Gradle使用依賴的栗子
          
             
          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());
          List  phoneList = personOut.getPhoneList();
          for (Message.Person.Phone phone : phoneList)
          {
              System.out.printf( "手機(jī)號(hào):%s (%s)\n", phone.getNumber(), phone.getType());
          }

          比較

          為了能體現(xiàn)ProtoBuf的優(yōu)勢(shì),我寫了同樣結(jié)構(gòu)體的Java類,并且將Java對(duì)象轉(zhuǎn)換成JSON數(shù)據(jù),來(lái)與ProtoBuf進(jìn)行比較。JSON編譯庫(kù)使用Google提供的GSON庫(kù),JSON的部分代碼就不貼出來(lái)了,直接展示結(jié)果。關(guān)注頂級(jí)架構(gòu)師公眾號(hào)回復(fù)“offer”,送你一份驚喜禮包。

          比較結(jié)果結(jié)果

          運(yùn)行 1 次
          
             
          【 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
          運(yùn)行 10 次
          
             
          【 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
          運(yùn)行 100 次
          
             
          【 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
          運(yùn)行 1000 次
          
             
          【 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
          運(yùn)行 1萬(wàn) 次
          
             
          【 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
          運(yùn)行 10萬(wàn) 次
          
             
          【 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é)

          編解碼性能

          上述栗子只是簡(jiǎn)單的采樣,實(shí)際上據(jù)我的實(shí)驗(yàn)發(fā)現(xiàn)
          • 次數(shù)在1千以下,ProtoBuf 的編碼與解碼性能,都與JSON不相上下,甚至還有比JSON差的趨勢(shì)。

          • 次數(shù)在2千以上,ProtoBuf的編碼解碼性能,都比JSON高出很多。

          • 次數(shù)在10萬(wàn)以上,ProtoBuf的編解碼性能就很明顯了,遠(yuǎn)遠(yuǎn)高出JSON的性能。

          內(nèi)存占用

          ProtoBuf的內(nèi)存34,而JSON到達(dá)106 ,ProtoBuf的內(nèi)存占用只有JSON的1/3.

          結(jié)尾

          其實(shí)這次實(shí)驗(yàn)有很多可待優(yōu)化的地方,就算是這種粗略的測(cè)試,也能看出來(lái)ProtoBuf的優(yōu)勢(shì)。關(guān)注頂級(jí)架構(gòu)師公眾號(hào)回復(fù)“架構(gòu)整潔”,送你一份驚喜禮包。

          兼容

          新增字段

          • 在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=
          結(jié)果,是可以轉(zhuǎn)換成功。

          刪除字段

          • 在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)
          結(jié)果,是可以轉(zhuǎn)換成功。


            開(kāi)發(fā)者全社區(qū) 

          5T技術(shù)資源大放送!包括但不限于:Android,Python,Java,大數(shù)據(jù),人工智能,AI等等。關(guān)注公眾號(hào)后回復(fù)「2T」,即可免費(fèi)獲取!!
          瀏覽 42
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美逼毛 | 殴美日韩中文在线中 | 9797人妻 | 黄色一级片免费直播 | 先锋影音av成人版 |