Swoole性能优化和压测结果分享
大家好,在 v5.1.0 到 v5.1.4 这几个版本中,Swoole 官方开发团队对 HTTP 服务器进行了大量性能优化,性能得到了巨大的提升。于是趁这个机会跟大家简单汇报一下成果。
为什么要优化#
其实在 TechEmpower 的几次压测中,Swoole 并没有取得令人特别满意的成绩。因此从去年开始,我们断断续续花了很久的时间对 Swoole 做了一些优化。
优化的成果#
因为 TechEmpower 换了特别好的服务器作为新的压测环境,所有框架的压测结果比以往好了很多倍。详细可以看看这个 issue。历史成绩之间差距变大了,所以这里采用 Swoole 的排名变化作为优化结果。
未优化前在 TechEmpower Round 21 的测试中,Swoole 在 PHP 框架中排名第 7,可以点击这里看看详情。
优化后在 TechEmpower 最近的一周一测中,Swoole 在 PHP 框架中排名第 2,可以点击这里看看详情。
可以看到经过优化后的 Swoole 的压测性能比以往优秀了不少,感兴趣的朋友可以访问这个网站看看最近的压测信息。
性能瓶颈#
我们一开始通过 perf 和 wrk 生成了程序执行的火焰图,旨在分析出 Swoole 在作为 HTTP 服务器的过程中执行函数的耗时情况。并且总结出了一些问题:
- 同一个连接发来的多个请求,Swoole 总会重复获取客户端 ip。
- Swoole\Http\Resquest::server 属性默认初始大小为 8 会导致一次数组扩容和内存拷贝。
- 每个不同的请求,它们的 Swoole\Http\Resquest 或者 Swoole\Http\Response 中,有些数组或者属性里面的 key 都是一样的,区别在于 value 不一样。但是我们却会为每个 key 单独申请内存。
- 初始化或者读取 Swoole\Http\Resquest 和 Swoole\Http\Response 的属性的过程中,ZEND_API 提供的函数太过繁琐。
- 有些遗留的析构函数并没有去掉,在整个生命周期中还在执行。
- 压测的代码没法发挥 Swoole 的性能。
解决方案#
针对问题 1,我们的思路是,如果客户端 ip 是本地回环地址 127.0.0.1,直接将这个 ip 地址写入数组中。如果不是,通过缓存的形式,将客户端 ip 缓存起来。减少 ip 的获取次数。
针对问题 2,我们计算过,server 属性只有 10 个,初始化数组的过程中直接设置数组大小为 16,解决数组扩容和内存拷贝。
针对问题 3,我们将相同的,只读的数组 key 名作为关键字符串,让它们的生命周期变成永久的。所有的请求共用相同的 key。减少内存的申请和释放。
针对问题 4,我们知道,php 的对象实例化后,其内部的属性保存在一个柔性数组中,也就是属性的在结构体中的位置是固定的,读写属性的时候根据 zend_class_entry 先获取属性的偏移量,这样可以从对象的柔性数组中获取对应的属性。再加上 Swoole 的内置类的属性在初始化的时候只有简单的赋值操作,而且属性一定存在并且没有动态属性。所以可以直接通过指针操作对象的 zval,而不通过 ZEND_API 操作。
针对问题 5,把没用的析构函数删了就行。
针对问题 6,我们按照 TechEmpower 的压测规范,重新设计了压测代码,将压测环境的容器由 php:8.3-cli 换成 ubuntu24.04。
经过在上面的几步操作,Plaintext 和 JSON serialization 的成绩已经相当可观了,然后在优化 Single query,Multiple queries,Fortunes 和 Data updates 过程中我们发现,php 的各个网络引擎或者框架都是通过 pdo 扩展进行数据库操作,所以在这个阶段的成绩都差不多。那么在 pdo 这边做优化就不太现实了,因此我们转换了以下的思路:
Swoole 在发送数据的时候,如果响应体大于 4k,也就是一页,响应头和响应体会直接经过两次套接字发送。否则就将响应体拼接在响应头后面,经过一次套接字发送。这里设计是因为系统调用时间比内存复制会快。但是我们认为这里的话 4k 还是有点偏小了,需要找到一个的合适的值。
于是我们经过 8k,16k,32k 和 64k 的测试,我们发现在数据小于 16k 的时候,响应体拼接在响应头后面通过一次套接字发送出去效果会更好,否则就需要分两次发送。但是有意思的是,这个优化对于像 Data updates 这种有多次数据库 IO 和返回大数据的情况下,能提高的性能可能就几百左右,因为这个阶段数据库 IO 反而占了性能问题的大头。
结束语#
很感谢大家能看到这里,以上都是比较简略的说明,以后有时间会写详细的优化过程,未来也会着手对协程或者 SWOOLE_PROCESS 模式等等的优化工作。也很感谢大家对 Swoole 的支持和鼓励,祝愿大家在未来的日子里身体健康,工作顺利,万事如意。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: