PHP序列化对比(Protobuf&Json)

概念

测试脚本

  • 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测试脚本
<?php
/**
 * @name   序列化调研
 * @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,
        '_',
        '!',
        '@',
        '#',
        '$',
        '%',
        '^',
        '&',
        '*',
        '(',
        ')',
        '-',
        '+',
        '=',
        '阿',
        '萨',
        '德',
        '额',
        '人',
        '哦',
        '吗',
        '从',
        '是',
        '去',
        '吧',
        '你',
        '放',
        '如',
    );

    /**
     * 运行入口
     */
    public function run(){

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

    /**
     * 运行测试数据
     * @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,
        );
    }

    /**
     * 构造数据
     * @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);
        }
    }

    /**
     * 获得随机字符串
     * @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();

  • 执行测试脚本
    php index.php

  • 输出结果

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

深入了解原理请访问
http://www.jianshu.com/p/ec39f79c0412

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • 星期六,大风 时间过得真快,今天又是许悦去辅导班的时间,一早起来就准备,呵呵今天特积极。晚上回家姐妹俩去看她奶奶,...
    许悦妈妈阅读 224评论 0 1
  • 走进 蓝蓝的天空,清爽的空气! 猜!这是什么。 再没有哪个季节...
    钰馨Lucy阅读 208评论 0 0
  • 好久没回来了,差一点就又放弃了 ahaha 硕士话,这几天是真的有点累的。完成了PCB的绘制,元件的选购,到焊接的...
    乂洛克阅读 219评论 0 0
  • 职业生涯,目标决定以后的生活。即使是阶段性的也很好。哪怕是用几年的时间去最求自己喜欢的人,也许最后在一起了,结...
    精彩阿曦阅读 182评论 0 0