1

上記の関数を使用してクラス メソッドを呼び出し、配列を使用してメソッド呼び出しを動的に埋める場合のベスト プラクティスについて考えていました。

どのような利点と欠点がありますか? つまり、特定の条件では、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

どちらを使用するのが良いのか、そしてその理由を知りたいだけです! ただし、速度とは厳密には関係ありません。

4

1 に答える 1

5

テスト結果をどこで取得したかはわかりませんが、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
)

実写を見る

于 2012-11-25T22:32:40.617 に答える