2012-11-25 2 views
1

위의 함수를 사용하여 클래스 메서드를 호출하여 배열을 사용하여 동적으로 메서드 호출을 채우는 것이 가장 좋은 방법에 대해 궁금합니다.call_user_func_array 대 ReflectionMethod

어떤 장점과 단점이 있습니까? 내 말은, 그것은 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 

결과! 그 엄격하게 속도와 관련이 없다! 당신이 당신의 테스트 결과를 가지고 있지만 호출에만 단일 인스턴스 다중으로 할 수 있습니다 RefelectionMethod + invokeArgs option is up to 40% faster than the call_user_funcion 가져까지 보인다 곳

+0

" 내 말은, RefelectionMethod + invokeArgs 옵션이 call_user_funcion보다 최대 40 % 더 빠르다는 것입니다. "- 테스트 케이스를 추가 할 수 있습니까? – zerkms

+0

@zerkms이 문제에 대한 몇 가지 구체적인 테스트를 수행했지만 궁극적으로 질문 끝에 추가 할 것입니다. – Ivo

+0

알다시피, IDE에서 줄 간격을 조정할 수 있습니다 ... – phant0m

답변

4

확실하지

간단한 벤치 마크

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