PHPの【クロージャー、クラスのnew、クローン】の比較

  • 12
    いいね
  • 7
    コメント
この記事は最終更新日から1年以上が経過しています。

【訂正】

速度の比較で、関数だけは実行時間が入っていたので、比較対象から外しました。それにともなって、タイトルを変更しました。

【/訂正】

PHPのクロージャーのおかげで、コードをデータのように使えるようになりました。ちょっとした設定とか、コードで記述できて便利です。

ところで、パフォーマンスはどうなのでしょう?
PHPの内部では、クロージャーは__invokeのあるオブジェクトとして実装されている、と聞いているので、おそらくクラスをnewするのと似たような速度かなと思います。今さらながら、遅かったらどうしよう、という疑問が…

ということで計測してみました。

比較対象は、クロージャー、クラスをnew、ついでにクローンと関数も比較してみました。

結果

     closure:   491.33  msec
   new class:   437.70  msec
   clone obj:   353.54  msec

実行環境:mac mini, Core i7, 16GB, PHP5.6.16

感想

予想通り、クロージャーもnewも似たような数字になりました。少しnewの方が速いのですね。クロージャーのほうが、少し複雑なオブジェクトなのかもしれません。

意外だったのが、関数呼び出しが一番遅かったこと。

関数にするより、クロージャー使ったりオブジェクトを作るほうが速いとは。と言っても、3〜4倍程度なので、そもそもが速いので、気にすることはないですが。

クローンは速いと聞いてたのですが、やはり一番早かったです。でも、似たような数字ですね。

PHP7

PHP7でも試してみたいですね。
同じく導入される無名クラスも、一応測ってみたい。

結論

コードによる速度差なんか気にしなくてOK!

コード

測定に使ったコードです。

<?php

function runIt($closure, $title)
{
    $n = 1000000;
    $time1 = microtime(true);
    $closure($n);
    $time2 =  microtime(true);

    echo sprintf("%12s: %8.2f  msec\n", $title, ($time2 - $time1) * 1000);
};

$do_closure = function ($n = 100)
{
    for($i = 0; $i < $n; $i++) {
        $s = function() use($i) {return 'hi';};
    }
};

class sample {
    function __invoke() {
        return 'hi';
    }
}

$do_class = function ($n = 100)
{
    for($i = 0; $i < $n; $i++) {
        $s = new sample($i);
    }
};

$do_clone = function ($n = 100)
{
    $s0 = new sample();
    for($i = 0; $i < $n; $i++) {
        $s = clone $s0;
    }
};

function test_func($i) {
    return 'hi';
}
$do_function = function ($n = 100)
{
    for($i = 0; $i < $n; $i++) {
        $s = test_func($i);
    }
};

//runIt($do_function, 'function');
runIt($do_closure, 'closure');
runIt($do_class, 'new class');
runIt($do_clone, 'clone obj');