2012-11-25 57 views
1

我在想使用上述函數調用一個類方法來填充一個使用數組的動態方法調用時的最佳實踐是什麼?call_user_func_array vs ReflectionMethod

我有什麼優點和缺點?我的意思是,在某些情況下,RefelectionMethod + invokeArgs選項似乎比call_user_funcion快40%...但我錯過了什麼嗎?

謝謝。

按照要求我會添加一個我的場景的基準,我需要通過refereces ...我知道它是一個非常具體的案例,這不是嚴格地與上述問題相關!

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 

我真的只是想知道什麼時候它能夠更好地使用一個與其他的,爲什麼!它與速度並不嚴格相關!

+0

「我的意思是,看來RefelectionMethod + invokeArgs選項比call_user_funcion快40% - 「你能爲此添加一個測試用例嗎? – zerkms

+0

@zerkms我已經完成了很少和特定的測試,但我最終將它們添加到問題的末尾:) – Ivo

+0

您知道,您可以在IDE中調整行間距... – phant0m

回答

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