call_user_func_array vs ReflectionMethod

时间:2012-11-25 22:04:43

标签: php

我想知道在使用上面的函数调用类方法以使用数组动态填充方法调用时最佳实践是什么!

我有哪些优点和缺点?我的意思是,在某些情况下,似乎RefelectionMethod + invokeArgs选项比call_user_funcion快40%......但是我会错过什么吗?

感谢。

根据要求,我将添加一个我的场景的基准,我需要通过的参考...我知道它是一个非常具体的案例,这与上述问题没有严格的关联!

class foo { public function bar(&$a, &$b, &$c) { /* */ } }
$t1 = microtime(true);
$arr = array(1,2,3);
$foo = new foo;
$rfl = new ReflectionMethod('foo', 'bar');
for ($i=0; $i < 10000; ++$i)
{   
    $rfl->invokeArgs($foo, $arr);   
}

$t2 = microtime(true);
echo sprintf("\nElapsed reflectionmethod  : %f", $t2 - $t1);
$t1 = microtime(true);
$arr = array(1,2,3);
$foo = new foo;

for ($i=0; $i < 10000; ++$i)
{
    foreach( $arr as $k => $v ) $ref[$k] = &$arr[$k];       
    call_user_func_array( array($foo, 'bar'), $arr);
}

$t2 = microtime(true);
echo sprintf("\nElapsed calluserfuncarray : %f", $t2 - $t1);

结果

Elapsed reflectionmethod  : 0.025099
Elapsed calluserfuncarray : 0.051189

我真的想知道何时使用其中一种比较好,为什么!它与速度并不严格相关!

1 个答案:

答案 0 :(得分:4)

不确定您的测试结果在哪里,但RefelectionMethod + invokeArgs option is up to 40% faster than the call_user_funcion似乎很遥远,只有单实例多次调用才能实现

简单基准

set_time_limit(0);
echo "<pre>";
class Foo {

    public function bar($arg1, $arg2) {
    }
}

$globalRefection = new ReflectionMethod('Foo', 'bar');
$globalFoo = new Foo();

// Using call_user_func_array
function m1($args) {
    $foo = new Foo();
    call_user_func_array(array($foo,"bar"), $args);
}

// Using ReflectionMethod:invoke
function m2($args) {
    $foo = new ReflectionMethod('Foo', 'bar');
    $foo->invoke(new Foo(), $args[0], $args[1]);
}

// Using ReflectionMethod:invokeArgs
function m3($args) {
    $foo = new ReflectionMethod('Foo', 'bar');
    $foo->invokeArgs(new Foo(), $args);
}

// Using Global Reflection
function m4($args) {
    global $globalRefection;
    $globalRefection->invokeArgs(new Foo(), $args);
}

// Using Global Reflection + Glbal foo
function m5($args) {
    global $globalRefection, $globalFoo;
    $globalRefection->invokeArgs($globalFoo, $args);
}

$result = array('m1' => 0,'m2' => 0,'m3' => 0,'m4' => 0,'m5' => 0);
$args = array("arg1","arg2");

for($i = 0; $i < 10000; ++ $i) {
    foreach ( array_keys($result) as $key ) {
        $alpha = microtime(true);
        $key($args);
        $result[$key] += microtime(true) - $alpha;
    }
}

echo '<pre>';
echo "Single Run\n";
print_r($result);
echo '</pre>';

输出

Single Run
Array
(
    [m1] => 0.018314599990845   <----- call_user_func_array 
    [m2] => 0.024132013320923   <----- ReflectionMethod:invoke
    [m3] => 0.021934270858765   <----- ReflectionMethod:invokeArgs
    [m4] => 0.012894868850708   <----- Global Relection
    [m5] => 0.01132345199585    <----- Global Reflection + Global Foo
)

See Live Action