2

少し前まで、何らかのアクションを行った後、それ自体への代入変数について議論しました。

変数を自分自身に割り当てる [ AI ]:

echo memory_get_usage() . "\n"; // 645680
$repeatedString = str_repeat('Hello,', 10000);
echo memory_get_usage() . "\n"; // 705944, AI_delta1 = 60264
$repeatedString = explode(',', $repeatedString);
echo memory_get_usage() . "\n"; // 3337888, AI_delta2 = 2631944
echo memory_get_peak_usage() . "\n"; // AI_peak = 3401024

変数を別の変数に割り当てる [ AAV ]:

echo memory_get_usage() . "\n"; // 645752
$repeatedString = str_repeat('Hello,', 10000);
echo memory_get_usage() . "\n"; // 706024, AAV_delta1 = 60272
$explodedString = explode(',', $repeatedString);
echo memory_get_usage() . "\n"; // 3398256, AAV_delta2 = 2692232
echo memory_get_peak_usage() . "\n"; // AAV_peak = 3400984

どちらの場合もメモリ使用量のテストを作成し、値を減算します。

AAV_delta1 - AI_delta = 8
AAV_delta2 - AI_delta2 = 60288
AAV_peak - AI_peak = -40

この結果によると、使用するアプローチ、メモリ使用量は同じです。$repeatedString 以下のコードで変数を使用するかどうかは問題です。

私の結論は正しいですか、それとも私のテストは正しくありませんか?

なぜこのようになるのでしょうか?

また質問: AAV_delta1 - AI_delta = 8、私はそれが 0 に等しいはずだと思います。なぜ 8 に等しいのですか?

注: メモリ使用量はシステムによって異なる場合があります。

PHP バージョン: 5.3.5-1ubuntu7.11。

4

1 に答える 1

4

AAV では、各変数がそのデータを保持する必要があるため、データのコピーが 2 つあります。どちらも、それぞれの変数が再割り当てされるか範囲外になるまで存続する必要があります。

AI では、データのコピーが一時的に2 つ存在します。割り当てが行われると、元の値は不要になります。ただし、使用するメモリは、ガベージ コレクションが行われるまで回復されません。

代入の直後にメモリ使用量を確認しても、おそらくまだ GC が行われていないため、違いに気付くことはありません。GC を強制すると、AI が AAV よりも少ないメモリを使用することがわかるはずです。

また、割り当て後に元の変数を設定解除することで、AAV で同じメモリ使用量の改善を得ることができます (これをAAVUと呼びます)。

$explodedString = explode(",", $repeatedString);
unset($repeatedString); // or $repeatedString = false;

AI と同様に、メモリ使用量の減少をすぐに GC に通知させる必要があります。

アップデート:

PHP は通常のメモリ管理に参照カウントを使用するため、AI は文字列で使用されているメモリをすぐに回収する必要があります。文字列は参照カウント 1 で始まります。 に渡されるexplode()と、refcount は 2 に増加します (explode のパラメータ変数による参照用)。がexplode()戻ると、パラメーター変数のスコープが終了し、refcount が 1 に戻ります。次に、への代入$repeatedStringが行われると、refcount が 0 になり、文字列のメモリが解放されます。

gc_collect_cycles()サイクルの一部である配列とオブジェクトによって使用されるメモリを再利用するためにのみ必要です。この影響を確認するには、次のコードを試してください。

gc_enable();
echo "Begin: " .  memory_get_usage() . "\n";
$array = array(str_repeat('Hello,', 10000));
$array[] =& $array; // Create circular reference
echo "After allocate: " . memory_get_usage() . "\n";
unset($array);
echo "After unset: " . memory_get_usage() . "\n";
gc_collect_cycles();
echo "After GC: " . memory_get_usage() . "\n";

結果:

Begin: 226088
After allocate: 286640
After unset: 286552
After GC: 226088

詳細については、PHP ガベージ コレクションのドキュメントを参照してください。

于 2013-01-04T07:17:38.190 に答える