在最新的4.5.6
開發分支中,底層增長了2
個特殊的函數:php
swoole_substr_json_decode
swoole_substr_unserialize
這裏爲何要增長這兩個函數呢?有這樣一種場景。使用Swoole\Server
實現RPC
服務,在EOF
協議或長度協議通訊方式下,一個包可能有3
部分組成。shell
$packet = $header + $body + $footer
一般$header
和$footer
比較小,而$body
比較大,$body
可能會使用JSON
或PHP
序列化格式。若是要解析$body
數據,那麼就須要先進行substr
獲得$body
的字符串格式數據,再進行json_decode
和unserialize
操做。json
這會引發一次內存拷貝,$body_str = substr($packet, $header_length)
的過程會建立一個臨時字符串變量,再反序列化操做$body = json_decode($body_str)
以後,這個變量就會被釋放。segmentfault
// 先進行 substr,這時會產生內存拷貝,從 $packet 複製數據到 $body_str $body_str = substr($packet, 4, strlen($packet) - 4 - 2); // 反序列化以後 $body_str 這塊內存再也不使用,會在函數退出時釋放 $body = json_decode($body_str, true);
使用新增的兩個函數就能夠將substr
和反序列化
操做合二爲一。減小一次內存拷貝,從而提升性能。swoole
$body = swoole_substr_json_decode($packet, $header_length); $body = swoole_substr_unserialize($packet, $header_length);
<?php error_reporting(E_ALL); $a['hello'] = base64_encode(random_bytes(1000)); $a['world'] = 'hello'; $a['int'] = rand(1, 999999); $a['list'] = ['a,', 'b', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx']; $val = serialize($a); $str = pack('N', strlen($val)).$val."rn"; $n = 100000; $s = microtime(true); while($n--) { $l = strlen($str) - 6; // var_dump(unserialize(substr($str, 4, $l))); var_dump(swoole_substr_unserialize($str, 4, $l)); } echo "cost: ".(microtime(true)-$s)."n";
使用swoole_substr_unserialize
與substr + unserialize
相比,性能提高了12%
dom
htf@htf-ThinkPad-T470p:~/workspace/debug$ php s.php cost: 2.2559139728546 htf@htf-ThinkPad-T470p:~/workspace/debug$ php s.php cost: 1.9821600914001