74

PHP では、次のように、関数宣言のパラメーターの前にアンパサンドを追加することで、関数パラメーターを参照によって渡すことができます。

function foo(&$bar)
{
    // ...
}

現在、これはパフォーマンスを向上させるためではなく、関数が通常はスコープ外の変数を変更できるようにするために設計されていることを認識しています。

代わりに、PHP は Copy On Write を使用して、変更されるまでオブジェクト (および場合によっては配列も) のコピーを回避しているようです。そのため、パラメーターを変更しない関数の場合、参照によって渡した場合と同じ効果が得られます。

ただし、Copy On Write ロジックが参照渡しでショートサーキットされている可能性があるかどうか、およびそれがパフォーマンスに影響を与えるかどうかは疑問でした。

ETA: 確かに、高速ではないと思いますし、これが参考文献の目的ではないことも十分承知しています。だから私自身の推測はかなり良いと思います.ボンネットの下で何が起こっているのかを本当に知っている誰かからの答えを探しているだけです. PHP の開発に 5 年間携わってきましたが、ソースを読むだけでは PHP の内部構造に関する質の高い情報を得るのが難しいといつも感じていました。

4

9 に答える 9

90

20 kB の文字列で関数を呼び出す 100,000 回の反復によるテストでは、結果は次のようになります。

パラメータを読み取る/使うだけの関数

pass by value:      0.12065005 seconds
pass by reference:  1.52171397 seconds

パラメータの書き込み・変更機能

pass by value:      1.52223396 seconds
pass by reference:  1.52388787 seconds

結論

  1. パラメータを値で渡す方が常に高速です

  2. 関数が渡された変数の値を変更する場合、実際には値渡しよりも参照渡しと同じです

于 2010-10-02T11:48:57.873 に答える
37

Zend Engine はコピー オン ライトを使用するため、自分で参照を使用すると、少し余分なオーバーヘッドが発生します。ただし、この言及は執筆時点でしか見つけることができず、マニュアルのコメントには他のリンクが含まれています。

(編集)オブジェクトと参照に関するマニュアル ページには、オブジェクト変数が参照とどのように異なるかについて、もう少し詳しい情報が含まれています。

于 2008-10-07T13:14:43.090 に答える
30

与えられた答えがよくわからなかったので、これについていくつかのテストを実行しました。

私の結果は、参照によって大きな配列または文字列を渡す方が大幅に高速であることを示しています。

ここに私の結果があります: 基準

Y 軸 (Runs) は、1 秒間に関数を呼び出すことができた回数 * 10 です。

テストは各関数/変数に対して8回繰り返されました

そして、ここに私が使用した変数があります:

$large_array = array_fill(PHP_INT_MAX / 2, 1000, 'a');
$small_array = array('this', 'is', 'a', 'small', 'array');
$large_object = (object)$large_array;
$large_string = str_repeat('a', 100000);
$small_string = 'this is a small string';
$value = PHP_INT_MAX / 2;

これらは関数です:

function pass_by_ref(&$var) {
}

function pass_by_val($var) {
}
于 2011-07-05T03:54:03.397 に答える
7

10kバイトの文字列の値と参照を2つの同一の関数に渡して実験しました。1 つは引数を値で受け取り、2 つ目は参照で受け取ります。それらは一般的な関数でした - 引数を取り、単純な処理を行い、値を返します。両方の呼び出しを 100 000 回行ったところ、参照はパフォーマンスを向上させるように設計されていないことがわかりました。参照の利益は 4 ~ 5% 近くで、文字列が十分に大きくなった場合にのみ増加します (100k 以上、6 ~ 7% の改善)。 . したがって、私の結論は、参照を使用してパフォーマンスを向上させないことです。これはそのためのものではありません。

PHPバージョン5.3.1を使用しました

于 2011-10-01T14:05:13.303 に答える
3

いいえ、それは速くないと確信しています。さらに、マニュアルでは、参照を使用してパフォーマンスを向上させようとしないように具体的に述べています。

編集:それがどこにあるのかわかりませんが、そこにあります!

于 2008-10-07T13:06:58.317 に答える
2

私が取り組んでいたプロジェクトに基づく実際の例で、これをベンチマークしようとしました。いつものように違いは些細なことですが、結果はやや予想外でした。私が見たほとんどのベンチマークでは、呼び出された関数は渡された値を実際には変更しません。単純な str_replace() を実行しました。

**Pass by Value Test Code:**

$originalString=''; // 1000 pseudo-random digits

function replace($string) {
    return str_replace('1', 'x',$string);
}
$output = '';
/* set start time */
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$tstart = $mtime;
set_time_limit(0);

for ($i = 0; $i < 10; $i++ ) {
    for ($j = 0; $j < 1000000; $j++) {
        $string = $originalString;
        $string = replace($string);
    }
}

/* report how long it took */
$mtime = microtime();
$mtime = explode(" ", $mtime);
$mtime = $mtime[1] + $mtime[0];
$tend = $mtime;
$totalTime = ($tend - $tstart);
$totalTime = sprintf("%2.4f s", $totalTime);
$output .= "\n" . 'Total Time' .
    ': ' . $totalTime;
$output .= "\n" . $string;
echo $output;

参照渡しテスト コード

以外は同じ

function replace(&$string) {
    $string = str_replace('1', 'x',$string);
}
/* ... */
replace($string);

秒単位の結果 (1000 万回の反復):

PHP 5
    Value:     14.1007
    Reference: 11.5564

PHP 7
    Value:     3.0799
    Reference: 2.9489

その違いは、関数呼び出しごとに数分の 1 ミリ秒ですが、このユース ケースでは、PHP 5 と PHP 7 の両方で参照渡しの方が高速です。

(注: PHP 7 のテストは、より高速なマシンで実行されました。PHP 7 の方が高速ですが、おそらくそれほど高速ではありません。)

于 2018-02-19T07:45:44.660 に答える
-3

オブジェクトを渡すときに & 演算子を追加する必要はありません。とにかく、PHP 5 以降のオブジェクトは参照によって渡されます。

于 2008-10-07T13:17:33.037 に答える