Zend Engine中的函数内联

 Zend Engine(PHP)特殊功能内联

现代PHP很快!它具有多项性能功能,例如OPCache,JIT和其他编译阶段的改进,可针对许多PHP应用程序进行智能优化。

检查OPCode是确保PHP可以进行最佳优化的简便方法。使用列出的OPCode,可以更清楚地了解给定的PHP代码段是否采用了执行预期任务所需的最短数量的OPCode。

目前,PHP有30多个这样的函数,它们使用特殊的OPCode或内联以提高性能。


展示这种效果的一个例子是 strlen函数。它返回给定字符串的长度,PHP尝试抢先优化。

if (strlen('Test') < 2) {
    echo "Test";
}

在此代码段中,该strlen函数在静态字符串文字上调用,并且PHP可以完全消除此块,因为Test字符串的长度是固定的,并且比较值也是静态值。

使用OPCode dump可以更好地揭示这一点

优化之前

php -d opcache.opt_debug_level=0x10000 test.php
0000 JMPZ bool(false) 0002
0001 ECHO string("Test")
0002 RETURN int(1)

优化后

php -d opcache.opt_debug_level=0x20000 test.php
0000 RETURN int(1)

此示例适用的其他方式也一样,通过摆脱不必要的JMPJMPZ/JMPNZ这将在PHP可以以其它方式使用操作码if块。

if (strlen('Test') < strlen('Test Test')) {
    echo "Test";
}
0000 ECHO string("Test")
0001 RETURN int(1)

因为strlen('Test') < strlen('Test Test')始终求值为true,所以优化的OPCode不包含任何跳转。

完全合格的功能名称

关于特殊函数处理的一个警告是,当在名称空间内进行特殊函数调用时,引擎无法使用特殊处理,因为稍后可能在程序中声明具有相同名称的函数。

namespace Foo;

if (strlen('Test') < strlen('Test Test')) {
    echo "Test";
}

请注意,if块是如何在Foo命名空间内的。OPCode转储显示PHP在此处应用特殊处理:

php -d opcache.opt_debug_level=0x20000 test.php
0000 INIT_NS_FCALL_BY_NAME 1 string("Foo\strlen")
0001 SEND_VAL_EX string("Test") 1
0002 V1 = DO_FCALL_BY_NAME
0003 INIT_NS_FCALL_BY_NAME 1 string("Foo\strlen")
0004 SEND_VAL_EX string("Test Test") 1
0005 V2 = DO_FCALL_BY_NAME
0006 T0 = IS_SMALLER V1 V2
0007 JMPZ T0 0009
0008 ECHO string("Test")
0009 RETURN int(1)

大多数现代PHP代码库都使用名称空间,并且要带回特殊处理,可以在函数名称前添加反斜杠(\)或在use function子句中添加别名。它们通常被称为“标准功能名称”。

namespace Foo;
if (\strlen('Test') < \strlen('Test Test')) {
    echo "Test";
}

或者

namespace Foo;
use strlen;
if (strlen('Test') < strlen('Test Test')) {
    echo "Test";
}

上面的两个片段都向引擎发出信号,表明这些strlen调用确实是针对内部strlen函数的,这使引擎可以继续并内联它们。

借助FQFN,引擎可以再次发挥其魔力:

0000 ECHO string("Test")
0001 RETURN int(1)

本文的要旨是,在调用PHP内部函数(特别是具有内联功能的函数)时,请始终使用完全限定的函数名来对它们进行引擎优化。

具有特殊处理的功能列表

以下所有功能在Zend Engine中都有特殊处理,如果被称为“完全合格的功能名称”,则可以从中受益。

列出最新版本,直到PHP 8.1资源

via https://php.watch/articles/php-zend-engine-special-inlined-functions

Zend Engine中的函数内联-使用完全限定函数名称提高PHP程序性能
标签: