5

PHPのドキュメントには、次のように書かれています。

パフォーマンスを向上させるために参照による戻りを使用しないでください。エンジンはこれを自動的に最適化します。

配列(私のクラスのプロパティ)への参照を返したいです。配列はオブジェクトではないため、PHPはこれをどのように最適化しますか?

配列に10億のエントリがある場合、参照で渡さないと、メモリに10億のエントリが格納された2つの配列を取得できませんか?

4

1 に答える 1

5

PHPはコピーオンライトを使用します。つまり、巨大な配列を関数パラメーターとして渡し、そこから読み取るだけの場合(foreachなど)、書き込みを行わないため、コピーを作成する必要はありません。

$count = count($huge_array); // read the reference at the bottom
for($i = 0; $i < $count $i++) {
    $value = 2*$huge_array[$i]/15;
    if($value > 3)
        $sub_array []= $value;
}

小さいはずの$subarray(これは巨大な配列のサブセットです)には、必要な(変更された)データのみが含まれます。

元の$huge_arrayの値を変更する予定がない場合、コピーされることはないため、余分なメモリは使用されません。

配列の元の値を変更する場合は、参照によって渡す必要があります。

元の配列の変更されたバージョンを作成して返す場合は、PHPが割り当てている追加のメモリが必要です。

元の配列の変更された小さいサブセットを作成して返す場合は、新しい空の配列を作成します。この配列に、巨大な配列からデータの一部をコピーし、$huge_arrayの値を上書きしないように注意する必要があります。 $ huge_arrayからの書き込みを避け、そこからの読み取りに重点を置きます。

このリンクは、PHPが値渡しのユースケース用に最適化されたことを説明しています。

コピーオンライトは、変数が値を期待する関数に渡される参照ではない場合にのみ機能します。参照が存在する場合は、値を渡すとコピーがトリガーされます。

これにより、引数が値によって渡されることを期待し、参照される変数を受け取ったPHPネイティブ関数が、参照の値をコピーします。

function foo(&$data) {
    for ($i = 0; $i < strlen($data); $i++) {
        do_something($data{$i});
    }
}

$string = "... looooong string with lots of data .....";
foo(string);

Cでstrlenを実行すると、文字列全体を反復処理してカウントすることになります。PHPでは、文字列には長さの値が付加されています。したがって、strlenはそこから読み取った値を返します(高速)。

ただし、参照変数を指定すると、長さを読み取る前にコピーする必要があるため、値を繰り返し処理して引数リストにコピーし、長さを読み取って返します(その後、新しくコピーした文字列のメモリを解放します) 。

于 2012-05-26T19:08:45.107 に答える