PHP序列化的四種實(shí)現(xiàn)方法與橫向?qū)Ρ冉坛?2)

2018-12-16 22:59:54 來源:互聯(lián)網(wǎng)作者:elarity 人氣: 次閱讀 561 條評(píng)論

在PHP中,序列化用于存儲(chǔ)或傳遞 PHP 的值的過程中,同時(shí)不丟失其類型和結(jié)構(gòu)。本文講述PHP序列化的四種方案,感興趣的可以了解一下一、PHP 序列化變量的 4 種方法序列化是將變量轉(zhuǎn)...

二、PHP四種序列化方案橫向?qū)Ρ?/strong>

數(shù)據(jù)的序列化是一個(gè)非常有用的功能,然而目測(cè)很多人跟我一樣,在剛接觸這玩意的時(shí)候壓根就不理解這貨色到底是干啥用的,反正老師說了,實(shí)在理解不了就先背過再說。

其實(shí)將數(shù)據(jù)序列化的作用無外乎有兩個(gè):

  • 方便傳輸
  • 方便存儲(chǔ)

方便存儲(chǔ)如何理解呢?比如我們有個(gè)PHP對(duì)象或者一個(gè)PHP數(shù)組需要存儲(chǔ)到數(shù)據(jù)庫(kù)甚至文件中,這顯然是不可能的,這個(gè)時(shí)候必須要將PHP對(duì)象或者PHP數(shù)組序列化后再執(zhí)行存儲(chǔ)操作。不過這將PHP數(shù)組序列化后存起來還能理解,這對(duì)象也能存儲(chǔ)???這操作是否過于風(fēng)騷?少年,這一點(diǎn)兒都不風(fēng)騷。有些時(shí)候?qū)?duì)象直接存儲(chǔ)起來,用的時(shí)候只需要簡(jiǎn)單的反序列化后就可以投產(chǎn)使用了,避免了new一次帶來的性能耗費(fèi)。

方便傳輸如何理解呢?其實(shí)序列化在傳輸中應(yīng)用的相對(duì)更多更常見些許。最簡(jiǎn)單的一個(gè)例子,一個(gè)碼前端的碼了一個(gè)ajax找你給TA提供一個(gè)API,那么這個(gè)時(shí)候你倆得商量返回什么數(shù)據(jù),比如json或者xml,甚至你倆自己作死約定私有數(shù)據(jù)格式。比如在一個(gè)比較典型的服務(wù)架構(gòu)中,網(wǎng)關(guān)服務(wù)器和內(nèi)部RPC服務(wù)器之間通過msgpack傳遞數(shù)據(jù)。這都是典型的序列化為了傳輸?shù)牡湫蛻?yīng)用案例。

這里序列化的概念可能更為廣泛和籠統(tǒng)一些,包括傳統(tǒng)的serialize、json、msgpack、protobuf等。( 如果你覺得序列化這個(gè)稱呼不太嚴(yán)謹(jǐn)?shù)脑?,可以用encode來代替;反序列化則用decode來代替。反正我就用統(tǒng)統(tǒng)用序列化和反序列化來稱呼了,如果你覺得實(shí)在不舒服,可以順著網(wǎng)線來砍我?。?。

實(shí)際上,從更高的層面看,數(shù)據(jù)的序列化可以分為兩種:

  • 文本序列化,常見如json、serialize、xml等
  • 二進(jìn)制序列化,常見如msgpack、protobuf、thrift等

一般說來,考驗(yàn)序列化技術(shù)的性能指標(biāo)一共有兩個(gè),一個(gè)是序列化的速度,一個(gè)是序列化后數(shù)據(jù)的大小,自然是序列化速度越快、序列化后的數(shù)據(jù)越小為佳。就目前來看,protobuf、msgpack等二進(jìn)制序列化無論是速度上還是數(shù)據(jù)大小上,都要比文本序列化更好。不過話說回來,文本序列化有更好的可讀性,一眼就能瞪出來數(shù)據(jù)內(nèi)容大概是啥玩意。

今天帶到這里的這里的有四個(gè)具體的方案,這四種方案都是簡(jiǎn)單粗暴、開箱即用類型的,我們分別測(cè)試感受下,看哪個(gè)更適合我們。

參會(huì)的四個(gè)哥們:PHP內(nèi)置的serialize、PHP內(nèi)置的JSON解析器、PHP擴(kuò)展JSOND、PHP擴(kuò)展msgpack。其中前三個(gè)都是文本類型的,msgpack則是二進(jìn)制類型的。

JSOND作為PHP內(nèi)置的JSON解析器的高級(jí)版本,坊間一直傳聞速度上要比內(nèi)置的更牛X一些,作為擴(kuò)展,這貨需要額外安裝,附送地址:https://pecl.php.net/get/jsond-1.4.0.tgz。

msgpack是一個(gè)鳥哥等人搞的一套二進(jìn)制序列化工具,slogan就是“It's like JSON.but fast and small.”,附送地址:https://pecl.php.net/get/msgpack-2.0.2.tgz

20181129112727957.jpg (800×371)

1、serialize用法
serialize(),序列化方法。
unserialize(),反序列化方法。

2、json用法
json_encode(),沒啥好說的吧?
json_decode(),沒啥好說的吧?

3、jsond用法
jsond_encode(),和json_encode()一樣,后面多個(gè)字母d而已。
jsond_decode(),和json_decode()一樣,后面多個(gè)字母d而已。

4、msgpack用法
msgpack_pack(),序列化方法。
msgpack_unpack(),反序列化方法。

測(cè)試代碼如下:

  1. <?php
  2. // 故意搞了一個(gè)還算大的php數(shù)組,更容易看出差距來
  3. $arr = array(
  4.  array(
  5.  'uid' => 22193123,
  6.  'gender' => 'famale',
  7.  'username' => 'elarity',
  8.  'password' => md5('www123'),
  9.  'relation' => array(
  10.  array(
  11.  'uid' => 22193123,
  12.  'gender' => 'famale',
  13.  'username' => 'elarity',
  14.  'password' => md5('www123'),
  15.  ),
  16.  array(
  17.  'uid' => 22193123,
  18.  'gender' => 'famale',
  19.  'username' => 'elarity',
  20.  'password' => md5('www123'),
  21.  ),
  22.  array(
  23.  'uid' => 22193123,
  24.  'gender' => 'famale',
  25.  'username' => 'elarity',
  26.  'password' => md5('www123'),
  27.  ),
  28.  array(
  29.  'uid' => 22193123,
  30.  'gender' => 'famale',
  31.  'username' => 'elarity',
  32.  'password' => md5('www123'),
  33.  ),
  34.  array(
  35.  'uid' => 22193123,
  36.  'gender' => 'famale',
  37.  'username' => 'elarity',
  38.  'password' => md5('www123'),
  39.  ),
  40.  array(
  41.  'uid' => 22193123,
  42.  'gender' => 'famale',
  43.  'username' => 'elarity',
  44.  'password' => md5('www123'),
  45.  ),
  46.  array(
  47.  'uid' => 22193123,
  48.  'gender' => 'famale',
  49.  'username' => 'elarity',
  50.  'password' => md5('www123'),
  51.  ),
  52.  array(
  53.  'uid' => 22193123,
  54.  'gender' => 'famale',
  55.  'username' => 'elarity',
  56.  'password' => md5('www123'),
  57.  ),
  58.  array(
  59.  'uid' => 22193123,
  60.  'gender' => 'famale',
  61.  'username' => 'elarity',
  62.  'password' => md5('www123'),
  63.  ),
  64.  ),
  65.  )
  66. );
  67.  
  68. // 每種序列化方案都執(zhí)行100000次
  69. $counter = 100000;
  70.  
  71. // json序列化方案,執(zhí)行100000次
  72. echo PHP_EOL.PHP_EOL;
  73. $start = microtime( true );
  74. for( $i = 1; $i <= $counter; $i++ ){
  75.  $json = json_encode( $arr );
  76. }
  77. $size = strlen( $json );
  78. $end = microtime( true );
  79. $cost_time = $end - $start;
  80. echo "json_encode : 耗費(fèi)時(shí)間為{$cost_time} , 數(shù)據(jù)體積為{$size}".PHP_EOL;
  81.  
  82. // jsond序列化方案,執(zhí)行100000次
  83. $start = microtime( true );
  84. for( $i = 1; $i <= $counter; $i++ ){
  85.  $jsond = jsond_encode( $arr );
  86. }
  87. $size = strlen( $jsond );
  88. $end = microtime( true );
  89. $cost_time = $end - $start;
  90. echo "jsond_encode : 耗費(fèi)時(shí)間為{$cost_time} , 數(shù)據(jù)體積為{$size}".PHP_EOL;
  91.  
  92. // serialize序列化方案,執(zhí)行100000次
  93. $start = microtime( true );
  94. for( $i = 1; $i <= $counter; $i++ ){
  95.  $serialize = serialize( $arr );
  96. }
  97. $size = strlen( $serialize );
  98. $end = microtime( true );
  99. $cost_time = $end - $start;
  100. echo "serialize : 耗費(fèi)時(shí)間為{$cost_time} , 數(shù)據(jù)體積為{$size}".PHP_EOL;
  101.  
  102. // msgpack序列化方案,執(zhí)行100000次
  103. $start = microtime( true );
  104. for( $i = 1; $i <= $counter; $i++ ){
  105.  $msgpack = msgpack_pack( $arr );
  106. }
  107. $size = strlen( $msgpack );
  108. $end = microtime( true );
  109. $cost_time = $end - $start;
  110. echo "msgpack耗費(fèi)時(shí)間為 : {$cost_time} , 數(shù)據(jù)體積為{$size}".PHP_EOL;
  111. echo PHP_EOL.PHP_EOL;

將文件保存為test.php,然后php test.php執(zhí)行,結(jié)果如下圖所示:

總結(jié)一下:

  • jsond確實(shí)是要比json快一些的
  • 總有刁民張嘴就來json要比serialize()快
  • serialize()數(shù)據(jù)體積確實(shí)大(因?yàn)檫€保留了數(shù)據(jù)類型說明)
  • msgpack最佳???不知道昂,你們自己感受