$a = array( '意味' => '人生', '数値' => 42 );
xdebug_debug_zval( 'a' );
エコー PHP_EOL;
クラステスト{
パブリック $a = 1;
パブリック $b = 2;
関数ハンドル(){
エコー「へへ」;
}
}
$test = 新しいテスト();
xdebug_debug_zval('テスト');
?>
実行結果は次のとおりです:
a:(refcount=1, is_ref=0),
配列
'意味' => (refcount=1, is_ref=0),
文字列
「人生」(長さ=4)
'数値' => (refcount=1, is_ref=0),
int
42
テスト:(refcount=1, is_ref=0),
オブジェクト(テスト)[1]
public 'a' => (refcount=2, is_ref=0),
int
1
public 'b' => (refcount=2, is_ref=0),
int
2
配列が配列の長さよりも 1 つ多い zval ストレージを使用していることがわかります。オブジェクトも似ています。配列のストレージ表現を以下に示します
ご覧のとおり、配列には 3 つの zval コンテナが割り当てられています: 意味する数字
それでは、いわゆる循環参照がどのように生成されるかを見てみましょう
$a = array( 'one' );
$a[] =& $a;
xdebug_debug_zval( 'a' );
?>
実行結果:
a:(refcount=2, is_ref=1),
配列
0 => (refcount=1, is_ref=0),
文字列
「1」(長さ=3)
1 => (refcount=2, is_ref=1)、&array
a は 1 と同じ zval コンテナです。以下の通り:
これは循環参照を形成します。
PHP 5.2 以前のバージョンには、特別なガベージ コレクター GC (ガベージ コレクション) がありません。エンジンは、変数空間を解放できるかどうかを判断するときに、変数の zval の refcount の値に依存します (refcount が 0 の場合)。場合は変数空間を解放できますが、それ以外の場合は解放されません。これは非常に単純な GC 実装です。
設定を解除すると ($a)、配列の refcount が 1 減って 1 になります。この zval を指す変数はなくなり、この zval のカウンターは 1 になり、リサイクルされません。
この構造体 (つまり、変数コンテナー) を指すスコープ内にシンボルはなくなりましたが、配列要素 "1" は依然として配列自体を指しているため、このコンテナーをクリアすることはできません。他にそれを指すシンボルがないため、ユーザーは構造体をクリアする方法がなく、メモリ リークが発生します。幸いなことに、PHP はリクエストの最後にこのデータ構造をクリアしますが、PHP がデータ構造をクリアする前に、メモリ内の大量のスペースを消費します。これは、解析アルゴリズムを実装している場合、または子要素がその親を指すようにするなどの他の作業を行っている場合によく発生します。もちろん、同じ状況がオブジェクトでも発生する可能性があります。実際、オブジェクトは常に暗黙的に参照されるため、オブジェクトで発生する可能性が高くなります。
上記の状況が 1 回か 2 回だけ発生する場合は問題ありませんが、メモリ リークが数千回、さらには数十万回発生した場合、これは明らかに大きな問題です。長時間実行されるスクリプトを実行すると、要求時にデーモンがほとんど終了しないなどの問題が発生する可能性があり、メモリ領域が消費され続け、メモリ不足によるクラッシュが発生します。
PHP5.3では、特別なアルゴリズム(より複雑)が使用されます。 、循環参照によって引き起こされるメモリ リークの問題に対処します。
zval がガベージである可能性がある場合、コレクション アルゴリズムは zval をメモリ バッファーに置きます。バッファーが最大臨界値 (最大値は設定可能) に達すると、リサイクル アルゴリズムはバッファー内のすべての zval を循環して、それらがガベージであるかどうかを判断し、解放処理を実行します。または、スクリプトで gc_collect_cycles を使用して、バッファ内のガベージを強制的にリサイクルします。
php5.3のGCでは、ガベージは次のように説明されています:
1: zval の refcount が増加する場合、この zval はまだ使用されており、間違いなくガベージではなく、バッファーには入りません
2: zval の refcount が 0 に減らされた場合、zval は GC によって処理されるガベージ オブジェクトではないため、バッファに入りません。
3: zval の refcount が削減後に 0 より大きい場合、zval は解放できず、zval はガベージになり、バッファーに置かれる可能性があります。 PHP5.3のGCはこのようなzval処理を対象としています。
ガベージコレクションメカニズムは、PHP 設定を変更することでオン/オフにすることができます。また、gc_enable() と gc_disable() を使用してプログラム内でオン/オフを切り替えることもできます。
ガベージ コレクション メカニズムをオンにすると、メモリ リークが発生した場合に大量のメモリ領域を節約できます。ただし、ガベージ コレクション アルゴリズムの実行には時間がかかるため、ガベージ コレクション アルゴリズムをオンにするとスクリプトの実行時間が長くなります。 。
以下はPHPマニュアルに記載されているスクリプトです
クラスフー
{
パブリック $var = '3.1415962654';
}
$baseMemory =memory_get_usage();
for ( $i = 0; $i
{
$a = 新しい Foo;
$a->self = $a;
if ( $i % 500 === 0 )
{
echo sprintf( '%8d: ', $i )、memory_get_usage() - $baseMemory, "n";
}
}
?>
このスクリプトの php5.2 および 5.3 でのメモリ使用量は、以下に示すように示されています。
次のスクリプトの場合
クラスフー
{
パブリック $var = '3.1415962654';
}
for ( $i = 0; $i
{
$a = 新しい Foo;
$a->self = $a;
}
echomemory_get_peak_usage(), "n";
?>
ガベージコレクションメカニズムがオンになっている場合、スクリプトの実行時間はオンになっていない場合に比べて 7% 増加します
通常、PHP のガベージ コレクション メカニズムは、リサイクル アルゴリズムが実際に実行されているときに消費時間を増加させるだけです。ただし、通常の (小規模な) スクリプトでは、パフォーマンスへの影響はまったくありません。
http://www.bkjia.com/PHPjc/938943.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/938943.html技術記事 PHP のガベージ コレクション メカニズムの詳細な説明 最近、PHP を使用してデーモン プロセスの実装をシミュレートするスクリプトを作成したため、PHP のガベージ コレクション メカニズムを深く理解する必要があります。この記事は...
を参照しています