关于swoole:Swoole-456-支持零拷贝-JSON-或-PHP-反序列化

在最新的4.5.6开发分支中,底层减少了2个非凡的函数:

  • swoole_substr_json_decode
  • swoole_substr_unserialize

这里为什么要减少这两个函数呢?有这样一种场景。应用Swoole\Server实现RPC服务,在EOF协定或长度协定通信形式下,一个包可能有3局部组成。

$packet = $header + $body + $footer

通常$header$footer比拟小,而$body比拟大,$body可能会应用JSONPHP序列化格局。如果要解析$body数据,那么就须要先进行substr失去$body的字符串格局数据,再进行json_decodeunserialize操作。

这会引起一次内存拷贝,$body_str = substr($packet, $header_length)的过程会创立一个长期字符串变量,再反序列化操作$body = json_decode($body_str)之后,这个变量就会被开释。

// 先进行 substr,这时会产生内存拷贝,从 $packet 复制数据到 $body_str
$body_str = substr($packet, 4, strlen($packet) - 4 - 2);
// 反序列化之后 $body_str 这块内存不再应用,会在函数退出时开释
$body = json_decode($body_str, true);

应用新增的两个函数就能够将substr反序列化操作合二为一。缩小一次内存拷贝,从而进步性能。

$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_unserializesubstr + unserialize相比,性能晋升了12%

htf@htf-ThinkPad-T470p:~/workspace/debug$ php s.php
cost: 2.2559139728546
htf@htf-ThinkPad-T470p:~/workspace/debug$ php s.php
cost: 1.9821600914001

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理