Swoole 4.5.6 支持零拷贝 JSON 或 PHP 反序列化

2020年10月22日

在最新的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."\r\n";

$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

 

展开阅读全文
2 收藏
分享
加载中
精彩评论
之前在微课听新华说官方守旧,让swoole用c写才给合并到官方…看来嘴上的牛逼不如用户的普及 👍
2020-10-23 07:04
2
举报
最新评论 (15)
支持swow,swoole吃相太难看,不支持win
2020-10-25 21:18
0
回复
举报
swoole不是纯c写的?
2020-10-23 18:34
0
回复
举报
c++和c混合
2020-10-24 13:47
0
回复
举报
Swow更轻量级?或者和jit避开某些问题?
2020-10-22 21:39
0
回复
举报
swow支持fpm 也支持windows
2020-10-22 23:45
0
回复
举报
这个不错
2020-10-23 07:02
0
回复
举报
swow的目标是合并到phpsrc
2020-10-22 23:50
0
回复
举报
之前在微课听新华说官方守旧,让swoole用c写才给合并到官方…看来嘴上的牛逼不如用户的普及 👍
2020-10-23 07:04
2
回复
举报
官方必须是c才合并,为了更好的维护,统一c,
2020-10-23 08:04
0
回复
举报
其实直接底层实现一个reader , decoder, encoder interface就好,传参用interface就不会有这些copy问题……
2020-10-22 19:21
0
回复
举报
所以swow和swoole两个扩展以后怎么选择?
2020-10-22 18:47
0
回复
举报
等swow release了官方会出说明。
2020-10-22 18:49
0
回复
举报
好的
2020-10-22 19:39
0
回复
举报
Swow?
2020-10-22 19:31
0
回复
举报
嗯 github搜一下
2020-10-22 20:29
0
回复
举报
更多评论
15 评论
2 收藏
分享
返回顶部
顶部