LoginSignup
8
7

More than 5 years have passed since last update.

PHPの参照渡しは本当に遅い?

Last updated at Posted at 2013-12-12

PHPが糞言語なのはどう考えても参照をポインタだと思っているお前らが悪い
http://tanakahisateru.hatenablog.jp/entry/2013/12/12/012728

で検証されている内容で、参照渡しの性能がどうしても気になったので、
本当に遅いのか試してみました。

検証コードはほとんど上記ブログのコピペで、
参照渡し後にreturnしないコードを追加しています。
こんな感じ。

<?php
function profile($funcname)
{
    $bigarray = range(1, 1000000);

    echo $funcname . "\n";

    if ($funcname) {
        $start = microtime(true);
        $ret = $funcname($bigarray, 500000);
        $end = microtime(true);
    } else {
        $start = microtime(true);
        $end = microtime(true);
    }

    echo "  caller memory: " . number_format(memory_get_usage()) . "\n";
    echo "  time: " . (($end - $start) * 1000) . "(ms)\n";
    unset($bigarray);
    unset($ret);
}

ob_start();
profile(null); // ウォームアップ
ob_end_clean();
// 参照なし
function nop_noref($arr)
{
    echo "  callee memory: " . number_format(memory_get_usage()) . "\n";
    return $arr;
}

// 参照渡しのみ
function nop_ref_arg(&$arr)
{
    echo "  callee memory: " . number_format(memory_get_usage()) . "\n";
    return $arr;
}

// 参照渡し+参照返し
function &nop_ref_both(&$arr)
{
    echo "  callee memory: " . number_format(memory_get_usage()) . "\n";
    return $arr;
}

// 参照渡しでreturnしない
function nop_ref_arg_noreturn(&$arr)
{
    echo "  callee memory: " . number_format(memory_get_usage()) . "\n";
}

profile('nop_noref');
profile('nop_ref_arg');
profile('nop_ref_both');
profile('nop_ref_arg_noreturn');

実行結果

% php -d memory_limit=-1 test.php
nop_noref
  callee memory: 136,495,512
  caller memory: 136,495,400
  time: 0.016927719116211(ms)
nop_ref_arg
  callee memory: 136,495,544
  caller memory: 232,884,184
  time: 81.586122512817(ms)
nop_ref_both
  callee memory: 136,495,608
  caller memory: 136,495,496
  time: 0.015974044799805(ms)
nop_ref_arg_noreturn
  callee memory: 136,496,160
  caller memory: 136,496,088
  time: 0.016212463378906(ms)

あんまり変わらない気がしますね。。

参照渡ししなければ中で書き換えた瞬間に巨大配列のコピーが発生しますが、
参照渡ししておけば書き換えてもコピーは発生しないので、用途によっては使って良い気がします。

ちなみに上記の各関数のechoの後ろに
$arr[] = null;
を追加すると以下のようになります。

% php -d memory_limit=-1 test.php
nop_noref
  callee memory: 136,496,608
  caller memory: 232,885,304
  time: 80.986022949219(ms)
nop_ref_arg
  callee memory: 136,496,632
  caller memory: 232,885,416
  time: 80.711841583252(ms)
nop_ref_both
  callee memory: 136,496,680
  caller memory: 136,496,616
  time: 0.015974044799805(ms)
nop_ref_arg_noreturn
  callee memory: 136,496,712
  caller memory: 136,496,688
  time: 0.017166137695312(ms)

半年前くらいに書いたコードが不発弾になってるんじゃないかと心配になって確かめたけど、
そんなことはなくてよかった。

検証に使用したのは化石バージョンです。

% php -v
PHP 5.2.17 (cli) (built: Nov  6 2013 15:05:14) 
8
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7