<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 的比較

          共 4014字,需瀏覽 9分鐘

           ·

          2020-12-12 01:49

          my.oschina.net/xiaolei123/blog/3085607

          介紹

          ProtoBuf 是google團隊開發(fā)的用于高效存儲和讀取結構化數據的工具。什么是結構化數據呢,正如字面上表達的,就是帶有一定結構的數據。比如電話簿上有很多記錄數據,每條記錄包含姓名、ID、郵件、電話等,這種結構重復出現。

          同類

          XML、JSON 也可以用來存儲此類結構化數據,但是使用ProtoBuf表示的數據能更加高效,并且將數據壓縮得更小。

          原理

          ProtoBuf 是通過ProtoBuf編譯器將與編程語言無關的特有的 .proto 后綴的數據結構文件編譯成各個編程語言(Java,C/C++,Python)專用的類文件,然后通過Google提供的各個編程語言的支持庫lib即可調用API。(關于proto結構體怎么編寫,可自行查閱文檔)

          ProtoBuf編譯器安裝

          Mac :?brew install protobuf

          舉個例子

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

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

          3. 編譯proto文件至Java版本

          • 用命令行 cd 到 src/main 目錄下

          • 終端執(zhí)行命令 : protoc --java_out=./java ./proto/*.proto

          • 會發(fā)現,在你的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?phoneList?=?personOut.getPhoneList();
          for?(Message.Person.Phone?phone?:?phoneList)
          {
          ????System.out.printf("手機號:%s?(%s)\n",?phone.getNumber(),?phone.getType());
          }

          比較

          為了能體現ProtoBuf的優(yōu)勢,我寫了同樣結構體的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

          總結

          編解碼性能

          上述栗子只是簡單的采樣,實際上據我的實驗發(fā)現

          • 次數在1千以下,ProtoBuf 的編碼與解碼性能,都與JSON不相上下,甚至還有比JSON差的趨勢。

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

          • 次數在10萬以上,ProtoBuf的編解碼性能就很明顯了,遠遠高出JSON的性能。

          內存占用

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

          結尾

          其實這次實驗有很多可待優(yōu)化的地方,就算是這種粗略的測試,也能看出來ProtoBuf的優(yōu)勢。

          兼容

          新增字段
          • 在proto文件中新增 nickname 字段

          • 生成Java文件

          • 用老proto字節(jié)數組數據,轉換成對象

          Id:1994,?Name:XIAOLEI
          手機號:100860?(HOME)
          手機號:100100?(MOBILE)
          getNickname=

          結果,是可以轉換成功。

          刪除字段
          • 在proto文件中刪除 name 字段

          • 生成Java文件

          • 用老proto字節(jié)數組數據,轉換成對象

          Id:1994,?Name:null
          手機號:100860?(HOME)
          手機號:100100?(MOBILE)

          結果,是可以轉換成功。

          瀏覽 28
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  免费在线观看黄片视频 | 黄色一级片日韩学生妹无套无码内射视频 | 妖精视频一区二区 | 欧美一级a一级a爱片免费 | 欧美精品系列 |