楼主

5671发表于 2019-11-28 14:14:45
只看该作者楼主

ARM64使能寄存器变量,PHP Zend引擎提升10%+性能 [复制链接]

今年做PHP 在ARM上的性能性能优化,利用GCC全局寄存器特性使提升PHPaarch64上性能提升10%。

源码修改已经提交到官方社区,随PHP 7.4以上官方版本发布。

发一篇帖子记录一下,对于PHP 7 , 不愿意升级PHP版本的,也可以修改几行代码,重新编译安装即可。

顺便总结了一下,利用GCC全局寄存器性能提升的内部原理和可用的推广点。

此性能优化点在PHPZend引擎中,任何使用PHP的场景都适用。

1 源码修改

源码修改涉及的2个文件如表1.所示。

1. 源码修改涉及文件

修改文件Zend_execute.czend.m4
源文件描述源码宏定义通用宏处理器,configure脚本依赖它

2个文件修改的内容均一致,总计新增3x2=6行代码。

修改后代码和源码对比如图1.所示。


1. PHP源码修改点

通过编译器的宏进行GCC版本判断和CPU类别判断,选取ARM64后两个通用寄存器x27x28。寄存器的使用方法如图2.所示。


2. Zend中寄存器使用

在并发访问worepress首页的场景中,获得了10%以上的性能提升。源码已合入PHP官方社区,将在PHP 7.4及以上版本发布。

2 内部原理

PHP Zend引擎在opcode的执行过程中,会频繁的用到execute_data(执行数据)和opline(当前执行的指令)两个变量。优化前的软件流程参考普通处理方式,优化后的软件流程参考全局寄存处理方式。


普通的处理方式


执行每条opcode指令的handler时,会把execute_data地址作为参数传给handler使用,先从当前栈上获取execute_data地址,然后再从堆上获取变量的数据(在缓存命中的情况下,从缓存中获取数据)。


GCC全局寄存器处理方式


使用GCC提供的全局寄存器特性保存execute_dataopline变量的地址在寄存器中,直接从寄存器读取地址。相对普通处理方式,节省了从缓存/内存中读取数据的时间。

3 技术推广

将频繁使用的charint或指针型变量存储在寄存器中,使用4.8.0以上GCC进行源码编译

4 附录

寄存器变量


寄存器变量存放在CPU的寄存器中,使用时,不需要访问内存直接从寄存器中读写,与存储在内存中的变量相比,寄存器变量具有更快的访问速度。 C语言中使用关键字register来声明变量为寄存器变量。受硬件寄存器长度的限制,寄存器变量只能是charint或指针型,而不能使其他复杂数据类型。


全局寄存器变量


GCC4.8.0版本开始支持另外一项特性:全局寄存器变量(Global Register Variables),可以把全局变量定义为寄存器变量,从而可以实现函数间共享数据。可以通过下面的语法告诉编译器使用寄存器来保存数据:


3 寄存器变量声明语法

全局寄存器变量详细介绍参考链接:

https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Global-Register-Variables.html



举报
发表于 2019-12-03 14:19:25
只看该作者沙发

干货,顶一顶~~~~~~~~~~~~~~

举报

您需要登录后才可以回帖

登录注册
发表回复