1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        序列化:ProtoBuf 與 JSON 的比較 !

        共 4452字,需瀏覽 9分鐘

         ·

        2020-12-07 03:02

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

        • 介紹
        • 同類
        • 原理
        • ProtoBuf編譯器安裝
        • 舉個(gè)例子
        • 比較
        • 比較結(jié)果結(jié)果
        • 總結(jié)
        • 結(jié)尾
        • 兼容

        介紹

        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é)果

        比較結(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ì)。

        兼容

        新增字段

        • 在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)換成功。

        題外話: 目前小哈正在個(gè)人博客(新搭建的網(wǎng)站,域名就是犬小哈的拼音)?www.quanxiaoha.com?上更新《Go語(yǔ)言教程》、《Gin Web框架教程》,畢竟Go自帶天然的并發(fā)優(yōu)勢(shì),后端的同學(xué)還是要學(xué)一下的,這個(gè)教程系列小哈會(huì)一直更新下去,歡迎小伙伴們?cè)L問(wèn)哦~

        END


        有熱門推薦?

        1.?IntelliJ IDEA 超實(shí)用技巧分享,不能再全了!

        2.?圖解 ElasticSearch 原理,你可收好了!

        3.?萬(wàn)字長(zhǎng)文詳解Shardingsphere對(duì)XA分布式事務(wù)的支持

        4.?SpringBoot集成Swagger-Bootstrap-UI,頁(yè)面更清爽!

        最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

        獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù)?Java?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

        文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。

        謝謝支持喲 (*^__^*)

        瀏覽 85
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            亚洲无码高清视频在线观看 | 中文字幕2页 | 五月天av影院 | 久热精品在线观看 | 国产精品久久久免费观看 | 丁香婷婷五月天精品 | 粗大挺进粉嫩紧窄的翘臀在线观看 | 一级成人免费视频午夜爱爱 | 冲田杏梨av电影 把腿扒开我添30分钟视频 | 震车做爰的视频 |