PHP 5 Reflection API性能

Fra*_*nck 56 php reflection performance

我目前正在考虑在我自己的MVC Web框架中使用Reflection类(主要是ReflectionClass和ReflectionMethod),因为我需要自动实例化控制器类并调用他们的方法而不需要任何必需的配置("约定优于配置"方法).

我担心性能,即使我认为数据库请求可能是比实际PHP代码更大的瓶颈.

所以,我想知道从性能的角度来看,是否有人对PHP 5 Reflection有任何好的或坏的体验.

此外,我很想知道任何一个流行的PHP框架(CI,Cake,Symfony等)是否实际使用Reflection.

Ali*_*xel 56

我对这3个选项进行了基准测试(另一个基准测试不是拆分CPU周期,而是4年前):

class foo {
    public static function bar() {
        return __METHOD__;
    }
}

function directCall() {
    return foo::bar($_SERVER['REQUEST_TIME']);
}

function variableCall() {
    return call_user_func(array('foo', 'bar'), $_SERVER['REQUEST_TIME']);
}

function reflectedCall() {
    return (new ReflectionMethod('foo', 'bar'))->invoke(null, $_SERVER['REQUEST_TIME']);
}
Run Code Online (Sandbox Code Playgroud)

1,000,000次迭代所需的绝对时间:

print_r(Benchmark(array('directCall','variableCall','reflectCall'),1000000));

Array
(
    [directCall] => 4.13348770
    [variableCall] => 6.82747173
    [reflectedCall] => 8.67534351
)
Run Code Online (Sandbox Code Playgroud)

相对时间,也有1,000,000次迭代(单独运行):

ph() - >转储(Benchmark(array('directCall','variableCall','reflectCall'),1000000,true));

Array
(
    [directCall] => 1.00000000
    [variableCall] => 1.67164707
    [reflectedCall] => 2.13174915
)
Run Code Online (Sandbox Code Playgroud)

似乎反射性能在5.4.7(从~500%下降到~213%)大大增加.

这是Benchmark()我使用的功能,如果有人想重新运行这个基准测试:

function Benchmark($callbacks, $iterations = 100, $relative = false)
{
    set_time_limit(0);

    if (count($callbacks = array_filter((array) $callbacks, 'is_callable')) > 0)
    {
        $result = array_fill_keys($callbacks, 0);
        $arguments = array_slice(func_get_args(), 3);

        for ($i = 0; $i < $iterations; ++$i)
        {
            foreach ($result as $key => $value)
            {
                $value = microtime(true);
                call_user_func_array($key, $arguments);
                $result[$key] += microtime(true) - $value;
            }
        }

        asort($result, SORT_NUMERIC);

        foreach (array_reverse($result) as $key => $value)
        {
            if ($relative === true)
            {
                $value /= reset($result);
            }

            $result[$key] = number_format($value, 8, '.', '');
        }

        return $result;
    }

    return false;
}
Run Code Online (Sandbox Code Playgroud)

  • +1为雄辩的回复和提供的细节. (2认同)
  • +1因为太棒了。你忘了提及 PHP 的版本。请注明这一点。 (2认同)

Kor*_*nel 55

不要担心.安装Xdebug并确保瓶颈在哪里.

使用反射需要花费成本,但这是否重要取决于您正在做什么.如果使用Reflection实现控制器/请求调度程序,那么每个请求只使用一次.绝对可以忽略不计.

如果使用反射实现ORM层,则将其用于每个对象甚至每次访问属性,并创建数百或数千个对象,然后它可能成本很高.


小智 18

在我的机器上调用静态功能100万次将花费约0.31秒.使用ReflectionMethod时,它的成本约为1.82秒.这意味着使用Reflection API的成本要高出约500%.

这是我使用的代码:

<?PHP

class test
{
    static function f(){
            return;
    }
}

$s = microtime(true);
for ($i=0; $i<1000000; $i++)
{
    test::f('x');
}
echo ($a=microtime(true) - $s)."\n";

$s = microtime(true);
for ($i=0; $i<1000000; $i++)
{
    $rm = new ReflectionMethod('test', 'f');
    $rm->invokeArgs(null, array('f'));
}

echo ($b=microtime(true) - $s)."\n";

echo 100/$a*$b;
Run Code Online (Sandbox Code Playgroud)

显然,实际影响取决于您希望进行的呼叫次数

  • 它可能要贵500%,但每次通话平均只有1.82微秒. (17认同)
  • 此测试不正确,因为反射方法的实例应该只创建一次.不在循环中. (5认同)

var*_*tec 5

此外,我很想知道任何一个流行的PHP框架(CI,Cake,Symfony等)是否实际使用Reflection.

http://framework.zend.com/manual/en/zend.server.reflection.html

"通常,此功能仅供框架的服务器类开发人员使用."


Xed*_*own 5

我想要更新的东西,所以看看这个 repo。从摘要:

  • 在反射的情况下,PHP 7 的速度几乎是 PHP 5 的两倍 - 这并不直接表明 PHP7 上的反射速度更快,PHP7 核心刚刚得到了很大的优化,所有代码都将从中受益。
  • 基本反射非常快——读取 1000 个类的方法和文档注释只需几毫秒。解析/自动加载类文件确实比实际的反射机制花费更多的时间。在我们的测试系统上,将 1000 个类文件加载到内存中大约需要 300 毫秒(需要/包含/自动加载) - 而在相同数量的类上使用反射解析(文档注释、getMethods 等)只需要 1-5 毫秒。
  • 结论:反射速度很快,在正常使用情况下,您可以忽略这种性能影响。但是,始终建议仅解析必要的内容。而且,缓存反射不会给您带来任何显着的性能优势。

另外,请查看另一个基准测试

这些结果是在使用 PHP 5.5.5 的开发 OS X 机器上获得的。[...]

  • 读取一个对象的单个属性:闭包稍微快一点。

  • 读取多个对象的单个属性:反射速度更快。

  • 读取对象的所有属性:闭包速度更快。

  • 在一个对象上编写单个属性:反射稍微快一点。

  • 在多个对象上编写单个属性:反射速度更快。