PHP序列化對(duì)比(Protobuf&Json)

概念

測(cè)試腳本

  • protobuf schema (test.proto)
message Test {
    optional int32 aaa = 1;
    repeated string bbb = 2;
}
  • 編譯test.proto
<?php
/**
 * Test message
 */
class Test extends ProtobufMessage
{
    /* Field index constants */
    const AAA = 1;
    const BBB = 2;

    /* @var array Field descriptors */
    protected static $fields = array(
        self::AAA => array(
            'name' => 'aaa',
            'required' => false,
            'type' => 5,
        ),
        self::BBB => array(
            'name' => 'bbb',
            'repeated' => true,
            'type' => 7,
        ),
    );

    /**
     * Constructs new message container and clears its internal state
     *
     * @return null
     */
    public function __construct()
    {
        $this->reset();
    }

    /**
     * Clears message values and sets default ones
     *
     * @return null
     */
    public function reset()
    {
        $this->values[self::AAA] = null;
        $this->values[self::BBB] = array();
    }

    /**
     * Returns field descriptors
     *
     * @return array
     */
    public function fields()
    {
        return self::$fields;
    }

    /**
     * Sets value of 'aaa' property
     *
     * @param int $value Property value
     *
     * @return null
     */
    public function setAaa($value)
    {
        return $this->set(self::AAA, $value);
    }

    /**
     * Returns value of 'aaa' property
     *
     * @return int
     */
    public function getAaa()
    {
        return $this->get(self::AAA);
    }

    /**
     * Appends value to 'bbb' list
     *
     * @param string $value Value to append
     *
     * @return null
     */
    public function appendBbb($value)
    {
        return $this->append(self::BBB, $value);
    }

    /**
     * Clears 'bbb' list
     *
     * @return null
     */
    public function clearBbb()
    {
        return $this->clear(self::BBB);
    }

    /**
     * Returns 'bbb' list
     *
     * @return string[]
     */
    public function getBbb()
    {
        return $this->get(self::BBB);
    }

    /**
     * Returns 'bbb' iterator
     *
     * @return ArrayIterator
     */
    public function getBbbIterator()
    {
        return new ArrayIterator($this->get(self::BBB));
    }

    /**
     * Returns element from 'bbb' list at given offset
     *
     * @param int $offset Position in list
     *
     * @return string
     */
    public function getBbbAt($offset)
    {
        return $this->get(self::BBB, $offset);
    }

    /**
     * Returns count of 'bbb' list
     *
     * @return int
     */
    public function getBbbCount()
    {
        return $this->count(self::BBB);
    }
}
  • php測(cè)試腳本
<?php
/**
 * @name   序列化調(diào)研
 * @author Rohn(253133755@qq.com)
 * @date   2017/7/6
 */
include 'pb_proto_test.php';

class SerializeTest
{

    private $test_data = array();
    private $data_json = array();
    private $data_pb = array();

    public $report = array();

    static $str = array(
        'a',
        'b',
        'c',
        'd',
        'e',
        'f',
        'g',
        'h',
        'i',
        'j',
        'k',
        'l',
        'm',
        'n',
        'o',
        'p',
        'q',
        'r',
        's',
        't',
        'u',
        'v',
        'w',
        'x',
        'y',
        'z',
        'A',
        'B',
        'C',
        'D',
        'E',
        'F',
        'G',
        'H',
        'I',
        'J',
        'K',
        'L',
        'M',
        'N',
        'O',
        'P',
        'Q',
        'R',
        'S',
        'T',
        'U',
        'V',
        'W',
        'X',
        'Y',
        'Z',
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9,
        0,
        '_',
        '!',
        '@',
        '#',
        '$',
        '%',
        '^',
        '&',
        '*',
        '(',
        ')',
        '-',
        '+',
        '=',
        '阿',
        '薩',
        '德',
        '額',
        '人',
        '哦',
        '嗎',
        '從',
        '是',
        '去',
        '吧',
        '你',
        '放',
        '如',
    );

    /**
     * 運(yùn)行入口
     */
    public function run(){

        $list = array(
            1000,
            3000,
            30000,
            100000,
            300000,
        );
        foreach($list as $test){
            $this->_do_run($test);
        }
        print_r($this->report);
    }

    /**
     * 運(yùn)行測(cè)試數(shù)據(jù)
     * @param $count
     */
    private function _do_run($count){

        $this->_get_data($count);
        $encode_report  = $this->_encode();
        $decode_report  = $this->_decode();
        $this->report[] = array_merge($encode_report, $decode_report);
    }

    /**
     * 序列化
     * @return array
     */
    private function _encode(){

        //json
        $this->data_json  = null;
        $s_mem            = memory_get_usage();
        $s_time           = microtime(true);
        $this->data_json  = json_encode($this->test_data);
        $e_time           = microtime(true);
        $e_mem            = memory_get_usage();
        $length_json      = number_format(mb_strlen($this->data_json) / 1024, 7, '.', '');
        $encode_meme_json = $e_mem - $s_mem;
        $encode_time_json = $e_time - $s_time;

        //protobuf
        $test_obj      = new Test();
        $this->data_pb = null;
        $test_obj->setAaa($this->test_data['aaa']);
        if(isset($this->test_data['bbb']) && count($this->test_data['bbb']) > 0){
            foreach($this->test_data['bbb'] as $b){
                $test_obj->appendBbb($b);
            }
        }
        $s_mem          = memory_get_usage();
        $s_time         = microtime(true);
        $this->data_pb  = $test_obj->serializeToString();
        $e_time         = microtime(true);
        $e_mem          = memory_get_usage();
        $length_pb      = number_format(mb_strlen($this->data_pb) / 1024, 7, '.', '');
        $encode_meme_pb = $e_mem - $s_mem;
        $encode_time_pb = $e_time - $s_time;
        $test_obj       = null;

        return array(
            'length_js'      => $length_json,
            'length_pb'      => $length_pb,
            'length_p'       => ($length_json - $length_pb) * 100 / $length_pb,
            'encode_mem_js'  => $encode_meme_json,
            'encode_mem_pb'  => $encode_meme_pb,
            'encode_mem_p'   => ($encode_meme_json - $encode_meme_pb) * 100 / $encode_meme_pb,
            'encode_time_js' => $encode_time_json,
            'encode_time_pb' => $encode_time_pb,
            'encode_time_p'  => ($encode_time_json - $encode_time_pb) * 100 / $encode_time_pb,
        );
    }

    /**
     * 解序列化
     * @return array
     */
    private function _decode(){

        //json
        $s_mem            = memory_get_usage();
        $s_time           = microtime(true);
        $d                = json_decode($this->data_json, 1);
        $e_time           = microtime(true);
        $e_mem            = memory_get_usage();
        $decode_meme_json = $e_mem - $s_mem;
        $decode_time_json = $e_time - $s_time;
        $d                = null;

        //protobuf
        $test_obj = new Test();
        $s_mem    = memory_get_usage();
        $s_time   = microtime(true);
        $test_obj->parseFromString($this->data_pb);
        $e_time         = microtime(true);
        $e_mem          = memory_get_usage();
        $decode_meme_pb = $e_mem - $s_mem;
        $decode_time_pb = $e_time - $s_time;
        $test_obj       = null;

        return array(
            'decode_mem_js'  => $decode_meme_json,
            'decode_mem_pb'  => $decode_meme_pb,
            'decode_mem_p'   => ($decode_meme_json - $decode_meme_pb) * 100 / $decode_meme_pb,
            'decode_time_js' => $decode_time_json,
            'decode_time_pb' => $decode_time_pb,
            'decode_time_p'  => ($decode_time_json - $decode_time_pb) * 100 / $decode_time_pb,
        );
    }

    /**
     * 構(gòu)造數(shù)據(jù)
     * @param $count
     */
    private function _get_data($count){

        $this->test_data['aaa'] = mt_rand(0, $count);
        for($i = 0; $i < $count; $i++){
            $this->test_data['bbb'][] = $this->get_str(100);
        }
    }

    /**
     * 獲得隨機(jī)字符串
     * @param $length
     * @return string
     */
    private function get_str($length){

        $data  = '';
        $count = count(self::$str);
        for($i = 0; $i < $length; $i++){
            $data .= self::$str[mt_rand(0, $count - 1)];
        }

        return $data;
    }
}

$s = new SerializeTest();
$s->run();

  • 執(zhí)行測(cè)試腳本
    php index.php

  • 輸出結(jié)果

Array
(
    [0] => Array
        (
            [length_js] => 176.8730469
            [length_pb] => 130.8339844
            [length_p] => 35.188917245877
            [encode_mem_js] => 181280
            [encode_mem_pb] => 134024
            [encode_mem_p] => 35.259356533158
            [encode_time_js] => 0.0026960372924805
            [encode_time_pb] => 0.00014805793762207
            [encode_time_p] => 1720.9339774557
            [decode_mem_js] => 297256
            [decode_mem_pb] => 296552
            [decode_mem_p] => 0.23739512800453
            [decode_time_js] => 0.0033869743347168
            [decode_time_pb] => 0.00016999244689941
            [decode_time_p] => 1892.4263674614
        )

    [1] => Array
        (
            [length_js] => 706.4111328
            [length_pb] => 522.8535156
            [length_p] => 35.106891648105
            [encode_mem_js] => 723528
            [encode_mem_pb] => 535440
            [encode_mem_p] => 35.127745405648
            [encode_time_js] => 0.010690927505493
            [encode_time_pb] => 0.00066089630126953
            [encode_time_p] => 1517.6406926407
            [decode_mem_js] => 1186200
            [decode_mem_pb] => 1185464
            [decode_mem_p] => 0.062085394410965
            [decode_time_js] => 0.013932943344116
            [decode_time_pb] => 0.00093817710876465
            [decode_time_p] => 1385.1080050826
        )

    [2] => Array
        (
            [length_js] => 6002.6904297
            [length_pb] => 4443.3632813
            [length_p] => 35.093397718851
            [encode_mem_js] => 6146920
            [encode_mem_pb] => 4550064
            [encode_mem_p] => 35.095242616368
            [encode_time_js] => 0.089380025863647
            [encode_time_pb] => 0.0054750442504883
            [encode_time_p] => 1532.4986936074
            [decode_mem_js] => 10321456
            [decode_mem_pb] => 10320736
            [decode_mem_p] => 0.0069762466552773
            [decode_time_js] => 0.11988496780396
            [decode_time_pb] => 0.0090479850769043
            [decode_time_p] => 1224.9907773386
        )

    [3] => Array
        (
            [length_js] => 23659.4199219
            [length_pb] => 17512.7265625
            [length_p] => 35.098437341915
            [encode_mem_js] => 24227408
            [encode_mem_pb] => 17933072
            [encode_mem_p] => 35.099039361466
            [encode_time_js] => 0.37850999832153
            [encode_time_pb] => 0.025068044662476
            [encode_time_p] => 1409.9302854208
            [decode_mem_js] => 40707576
            [decode_mem_pb] => 40706992
            [decode_mem_p] => 0.0014346429723916
            [decode_time_js] => 0.47448205947876
            [decode_time_pb] => 0.051760911941528
            [decode_time_p] => 816.68025481228
        )

    [4] => Array
        (
            [length_js] => 76635.7978516
            [length_pb] => 56723.3193359
            [length_p] => 35.104572068118
            [encode_mem_js] => 78475224
            [encode_mem_pb] => 58084816
            [encode_mem_p] => 35.104540918232
            [encode_time_js] => 1.1786558628082
            [encode_time_pb] => 0.0988929271698
            [encode_time_p] => 1091.850516048
            [decode_mem_js] => 129246120
            [decode_mem_pb] => 129245304
            [decode_mem_p] => 0.00063135756174166
            [decode_time_js] => 1.509269952774
            [decode_time_pb] => 0.13635492324829
            [decode_time_p] => 1006.8686900478
        )
)
  • 制作報(bào)表 https://docs.google.com/spreadsheets/d/1kU0HpUvcG-C6JK8GU-zKSxjKCewYt94lsRqNftaEfME/edit?usp=sharing

  • 報(bào)表

    • 數(shù)據(jù)報(bào)表
    • 數(shù)據(jù)大小
  • 內(nèi)存消耗
  • 耗時(shí)對(duì)比
  • 結(jié)論

  • protobuf比json在執(zhí)行時(shí)間上是最大的收益檩淋,至少一個(gè)數(shù)量級(jí)艳吠;

  • 其次是數(shù)據(jù)包的大小瓷患,protobuf比json少三分之二;

  • 序列化的內(nèi)存消耗protobuf是json的三分之一摧茴;

  • protobuf比json略麻煩一些叹谁,可以通過(guò)自動(dòng)化腳本優(yōu)化兴猩。

深入了解原理請(qǐng)?jiān)L問(wèn)
http://www.reibang.com/p/ec39f79c0412

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末期吓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子倾芝,更是在濱河造成了極大的恐慌讨勤,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晨另,死亡現(xiàn)場(chǎng)離奇詭異潭千,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)拯刁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)脊岳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人垛玻,你說(shuō)我怎么就攤上這事割捅。” “怎么了帚桩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵亿驾,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我账嚎,道長(zhǎng)莫瞬,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任郭蕉,我火速辦了婚禮疼邀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘召锈。我一直安慰自己旁振,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著拐袜,像睡著了一般吉嚣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蹬铺,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天尝哆,我揣著相機(jī)與錄音,去河邊找鬼甜攀。 笑死秋泄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的赴邻。 我是一名探鬼主播印衔,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼姥敛!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起瞎暑,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤彤敛,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后了赌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體墨榄,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年勿她,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了袄秩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逢并,死狀恐怖之剧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情砍聊,我是刑警寧澤背稼,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站玻蝌,受9級(jí)特大地震影響蟹肘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜俯树,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一帘腹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧许饿,春花似錦阳欲、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)书释。三九已至,卻和暖如春赊窥,著一層夾襖步出監(jiān)牢的瞬間爆惧,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工锨能, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扯再,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓址遇,卻偏偏與公主長(zhǎng)得像熄阻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子倔约,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 星期六,大風(fēng) 時(shí)間過(guò)得真快浸剩,今天又是許悅?cè)ポo導(dǎo)班的時(shí)間吏恭,一早起來(lái)就準(zhǔn)備,呵呵今天特積極。晚上回家姐妹倆去看她奶奶盏筐,...
    許悅媽媽閱讀 224評(píng)論 0 1
  • 走進(jìn) 藍(lán)藍(lán)的天空簿寂,清爽的空氣常遂! 猜圈匆!這是什么。 再?zèng)]有哪個(gè)季節(jié)...
    鈺馨Lucy閱讀 208評(píng)論 0 0
  • 好久沒(méi)回來(lái)了肤频,差一點(diǎn)就又放棄了 ahaha 碩士話汁雷,這幾天是真的有點(diǎn)累的。完成了PCB的繪制稍走,元件的選購(gòu),到焊接的...
    乂洛克閱讀 219評(píng)論 0 0
  • 職業(yè)生涯狐树,目標(biāo)決定以后的生活。即使是階段性的也很好鸿脓。哪怕是用幾年的時(shí)間去最求自己喜歡的人抑钟,也許最后在一起了,結(jié)...
    精彩阿曦閱讀 182評(píng)論 0 0