2011-06-26 7 views
3

create_functionの代わりにコールバックのクロージャを使用することを決定しました。そのため、PHP> 5.3はほとんどの場合、デバッグ性が向上していることを前提としています。 )私の状況でcreate_functionのオンザフライコンパイルのオーバーヘッドはおそらく、余分な比較やそのような関数内で作られなければならないものを相殺するだろうということです。PHPのクロージャまたはcreate_function

私のアプリケーションの場合はこれでも問題はないかもしれませんが、さらにテストする必要がありますが、私はcreate_functionメソッドが2倍以上速いというこの(非常に)簡単なテストの出力に興味がありました。 4つの条件文(およびコンカチ)のみを削除できる場合はクロージャを使用します。明らかに、私のテストケースでは余分な処理は行われていません。スピードの大部分が失われたり失われたりしますが、余分な処理はほとんどありませんが、コールバックが十分に呼び出されたとき、私はcreate_functionを使う方が良いかもしれないと考え始めました。

create_functionevalの明白な類似性はありますが、私は慎重です。

したがって、主な質問は、create_functionで作成された匿名関数とクロージャの関数との違いは何ですか?

evalの機能が無効になっている場合、create_functionも機能しますか?そして、私は最近、create_function関数が内部関数として宣言されていてもグローバル(またはクラス)名前空間を汚染すると最近読んだと確信していますが、クロージャはそうではありません。私は今これについての言及を見つけることができませんが、それらの言明のどちらかまたは両方が真ですか?


これは私が走った少しテストです:

<?php 

function foo($a=true, $b=true, $c=true, $d=true) 
{ 
    $inner1 = create_function(
     '', 
     '$r = \''.($a ? 'a' : ''). 
        ($b ? 'b' : ''). 
        ($c ? 'c' : ''). 
        ($d ? 'd' : '').'\'; 
     return $r;' 
    ); 


    $inner2 = function() use ($a, $b, $c, $d) 
    { 
     $r = ''; 
     if($a) { $r .= 'a'; } 
     if($b) { $r .= 'b'; } 
     if($c) { $r .= 'c'; } 
     if($d) { $r .= 'd'; }; 
     return $r; 
    }; 


    $time = microtime(true); 
    for ($x=0; $x<99999; ++$x) 
    { 
     $i1out = $inner1(); 
    } 
    echo '1:'.(microtime(true)-$time).'<br>'; 

    $time = microtime(true); 
    for ($x=0; $x<99999; ++$x) 
    { 
     $i2out = $inner2(); 
    } 
    echo '2:'.(microtime(true)-$time).'<br>'; 

    echo var_dump($i1out===$i2out).'<br>'; 
} 

foo(); 
+0

名前空間 'create_function'でテストするのはかなり簡単です。..関数を作成します。:) –

+0

私もクロージャーに行きます。スピードに関しては、実際のケースのシナリオでテストする必要があるかもしれません。なぜ私はそれがずっと遅くなければならないのか分かりませんが、私は「ヒット」をとるでしょう。また、APCはこのケースで違いを生みますか?オペコードにクロージャがキャッシュされていますか?それはまた違いを生むかもしれない。 – Arend

+0

分割してください。この質問はすでに...長いです。 – phihag

答えて

6

構造function() {..}は匿名関数であり、この機能は、多くの場合、closuresと一緒に実装されています。 create_functionも匿名関数もグローバル名前空間を汚染しません。

匿名関数は周囲の変数(クロージャー部分)にアクセスできるため、理論上わずかに遅くなります。一方、バイトコードキャッシングを使用している場合(そして、そうでない場合は、パフォーマンスについては明らかに心配していません)、私は匿名関数の「コンパイル」オーバーヘッドがわずかに遅くなることを期待しています。

ただし、匿名関数とcreate_functionの違いがパフォーマンス上の問題の原因になることはほとんどありません。したがって、私はあなたが幸運にもphp> 5.3のターゲットプラットフォームを持っているなら、より読みやすい形式の無名関数を選択したいと思います。

+1

まあ、それはあなたが "グローバルな名前空間を汚染する"という意味にかかっています。 'create_function'はグローバル関数を作成しますが、その名前は関数に使用する名前と競合しません。 – newacct

2

create_functionは、プログラムの残りの部分に対して持続するグローバル関数を作成します。 create_functionは関数名(文字列)を返すだけなので、何らかの形で保存されている名前にまだアクセスできるかどうかは分かりません。したがって、名前にアクセスできない場合でも、「ガベージコレクション」することはできません。(それは起こらないだろう、

for ($i = 0; $i < 1000000; $i++) { 
    $f = create_function('', ''); 
    // do stuff 

    // don't use $f anywhere after this point 
} 

無名関数を持つのに対し:あなたはcreate_functionを使用しての機能の多くを作成する場合、大きな問題があることを意味し

は、それはあなたのプログラムがメモリ不足になります閉鎖はガベージコレクションされます)。

関連する問題