ホームページ  >  記事  >  バックエンド開発  >  PHP のガベージ コレクション メカニズムについて詳しく学ぶ

PHP のガベージ コレクション メカニズムについて詳しく学ぶ

WBOY
WBOY転載
2022-08-25 11:51:111713ブラウズ

(推奨チュートリアル: PHP ビデオ チュートリアル)

1. 参照カウントの基礎知識

すべての php変数は、zval と呼ばれる変数コンテナーに保管されます。

zval 変数コンテナには、変数の型と値に加えて、2 バイトの追加情報も含まれています。

最初の変数は is_ref で、この変数が参照コレクションに属しているかどうかを識別するために使用されるブール値です。このバイトを通じて、PHP エンジンは通常の変数と参照変数を区別できます。PHP ではユーザーが & を使用してカスタム参照を使用できるため、zval 変数コンテナにはメモリ使用量を最適化するための内部参照カウント メカニズムもあります。

2 番目の追加バイトは refcount で、この zval 変数コンテナーを指す変数の数を示すために使用されます。

すべてのシンボルはシンボル テーブルに存在し、メイン スクリプト (例: ブラウザを通じて要求されたスクリプト) や各関数またはメソッドと同様に、各シンボルにスコープがあります。

2. zval コンテナの生成

変数に定数値が割り当てられると、zval 変数コンテナが生成されます

Xdebug がインストールされている場合は、xdebug_debug_zval() を使用できます。この 2 つを確認してください

<?php
$a = "new string";
xdebug_debug_zval(&#39;a&#39;);
 
//结果
a: (refcount=1, is_ref=0)=&#39;new string&#39;

3. zval の参照数を増やします

ある変数を別の変数に代入すると参照数が増加します

<?php
$a = "new string";
$b = $a;
xdebug_debug_zval( &#39;a&#39; );
 
//结果
a: (refcount=2, is_ref=0)=&#39;new string&#39;

4. zval の参照数を減らしますzval

unset()を使用すると参照数を減らすことができます

型と値を含む変数コンテナはメモリから削除されます

<?php
$a = "new string";
$c = $b = $a;
xdebug_debug_zval( &#39;a&#39; );
unset( $b, $c );
xdebug_debug_zval( &#39;a&#39; );
 
//结果
a: (refcount=3, is_ref=0)=&#39;new string&#39;
a: (refcount=1, is_ref=0)=&#39;new string&#39;

5. 複合型zvalコンテナ

  • スカラー型の値とは異なります
  • 配列およびオブジェクト型の変数は、メンバーまたは属性を独自のシンボル テーブルに格納します
  • これは次のことを意味します。この例では 3 つが生成されます。 zval 変数コンテナー
  • これら 3 つの zval 変数コンテナーは次のとおりです: a、意味、番号

<?php
$a = array( &#39;meaning&#39; => &#39;life&#39;, &#39;number&#39; => 42 );
xdebug_debug_zval( &#39;a&#39; );
 
//结果
a: (refcount=1, is_ref=0)=array (
   &#39;meaning&#39; => (refcount=1, is_ref=0)=&#39;life&#39;,
   &#39;number&#39; => (refcount=1, is_ref=0)=42
)

6. 型の複合参照数を追加します

既存の要素を配列に追加します

<?php
$a = array( &#39;meaning&#39; => &#39;life&#39;, &#39;number&#39; => 42 );
$a[&#39;life&#39;] = $a[&#39;meaning&#39;];
xdebug_debug_zval( &#39;a&#39; );
 
//结果
a: (refcount=1, is_ref=0)=array (
   &#39;meaning&#39; => (refcount=2, is_ref=0)=&#39;life&#39;,
   &#39;number&#39; => (refcount=1, is_ref=0)=42,
   &#39;life&#39; => (refcount=2, is_ref=0)=&#39;life&#39;
)

7.複合型の参照数を減らします

配列内の要素を削除します

は、スコープから変数を削除するのと似ています。

削除後、配列内の要素が配置されているコンテナーの「refcount」値は減少します

<?php
$a = array( &#39;meaning&#39; => &#39;life&#39;, &#39;number&#39; => 42 );
$a[&#39;life&#39;] = $a[&#39;meaning&#39;];
unset( $a[&#39;meaning&#39;], $a[&#39;number&#39;] );
xdebug_debug_zval( &#39;a&#39; );
 
//结果
a: (refcount=1, is_ref=0)=array (
   &#39;life&#39; => (refcount=1, is_ref=0)=&#39;life&#39;
)

8. 特殊なケース

配列自体をこの配列の要素として追加すると、興味深いことが起こります。

上記と同じように、変数に対して unset を呼び出すと、シンボルが削除され、その数は変数コンテナが指す変数コンテナ内の参照も 1

<?php
$a = array( &#39;one&#39; );
$a[] = &$a;
xdebug_debug_zval( &#39;a&#39; );
 
//结果
a: (refcount=2, is_ref=1)=array (
   0 => (refcount=1, is_ref=0)=&#39;one&#39;,
   1 => (refcount=2, is_ref=1)=...
)

9 削減されます。変数コンテナのクリーンアップの問題は問題ではなくなりましたが、

#特定のスコープでは、任意のシンボルがこの構造体 (つまり、変数コンテナー) を指していますが、配列要素 "1" は依然として配列自体を指しているため、このコンテナーをクリアすることはできません。

他にそれを指すシンボルがないため、ユーザーはこの構造をクリアする方法がなく、メモリ リークが発生します。

幸いなことに、PHP はスクリプトの実行の最後にこのデータ構造をクリアしますが、PHP がデータ構造をクリアする前に大量のメモリを消費します。

上記の状況が 1 回か 2 回だけ発生する場合は問題ありませんが、メモリ リークが数千回、さらには数十万回発生する場合、これは明らかに大きな問題です

10. リサイクル サイクル

これまで PHP で使用されていた参照カウント メモリ メカニズムでは、循環参照メモリ リークを処理できませんでした。

PHP 5.3.0 では、このメモリ リーク問題に対処するために同期アルゴリズムが使用されました。

参照カウントが増加すると、それは引き続き使用され、もちろんガベージには入れられなくなります。

参照カウントがゼロに減少すると、変数コンテナはクリアされます (解放)

つまり、ガベージ サイクルは、参照カウントがゼロに減少した場合にのみ発生します。 -zero value

ガベージ サイクルでは、参照カウントが 1 減っているかどうかを確認し、どの変数コンテナの参照がゼロであるかを確認することで、どの部分がガベージであるかを見つけます。

#ten 1. リサイクル アルゴリズムの分析

すべての参照カウントをチェックする必要を避けるために、ガベージ サイクルを減らすことができます

このアルゴリズムは、考えられるすべてのルート (考えられるルートは zval 変数コンテナー) をルート バッファー (紫色でマークされ、ガベージの疑いと呼ばれる) に配置するため、考えられるすべてのガベージを同時に確保できます。 ルート (ガベージ ルートの可能性がある)バッファ内に 1 回だけ表示されます。ガベージ コレクションは、ルート バッファーがいっぱいの場合にのみ、バッファー内のすべての異なる変数コンテナーに対して実行されます。上の画像のステップ A を見てください。

ステップ B では、紫色の各変数の削除をシミュレートします。削除をシミュレーションする際、紫色以外の通常変数の参照回数が「1」減る場合があり、通常変数の参照回数が0になった場合は、再度その通常変数の削除をシミュレーションしてください。各変数の削除をシミュレートできるのは 1 回だけであり、削除のシミュレート後は灰色でマークされます。

ステップ C では、シミュレーションによって紫色の各変数が復元されます。リカバリは条件付きであり、変数の参照カウントが 0 より大きい場合、シミュレートされたリカバリが実行されます。同様に、各変数は 1 回だけ復元できます。復元後は黒でマークされます。基本的にはステップ B の逆の操作です。このようにして、回復不能な青いノードの残りの山が削除されるべきです。ステップ D でそれらをトラバースし、実際に削除します。

12. パフォーマンスに関する考慮事項

主なものは 2 つあります。ドメインはパフォーマンスに影響を与えます

1 つはメモリ領域の節約です

もう 1 つは、ガベージ コレクション メカニズムがリークしたメモリを解放するのにかかる時間の増加です

13. ガベージ コレクション メカニズムの結論

PHP のガベージ コレクション メカニズムは、リサイクル アルゴリズムが実際に実行されているときに消費時間を増加させるだけです。ただし、通常の (小規模な) スクリプトでは、パフォーマンスへの影響はまったくありません。

ただし、リサイクル メカニズムが実行されている通常のスクリプトの場合、メモリの節約により、より多くのスクリプトをサーバー上で同時に実行できるようになります。使用メモリの合計が上限に達していないためです。

この利点は、長時間実行されるテスト スイートやデーモン スクリプトなど、長時間実行されるスクリプトで特に顕著です。

(推奨チュートリアル: PHP ビデオ チュートリアル)

以上がPHP のガベージ コレクション メカニズムについて詳しく学ぶの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjb51.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。