ホームページ  >  記事  >  バックエンド開発  >  PHP ガベージ コレクションのリサイクル戦略とアルゴリズム

PHP ガベージ コレクションのリサイクル戦略とアルゴリズム

WBOY
WBOYオリジナル
2016-06-13 12:03:04965ブラウズ

PHP ガベージ コレクションのリサイクル戦略とアルゴリズム

1. ガベージ コレクションの実装

では、以前は、参照カウント メカニズムが使用されていましたか?しかし、このメカニズムには欠点があり、循環参照によって引き起こされるメモリ リークを処理できないということです。ただし、php5.3.0 以降のバージョン (5.3.0 を含む) では、このメモリ リークの問題に対処するために、特別な GC メカニズム (同期アルゴリズム) を使用してガベージがクリーンアップされます。以下は、その実装方法の概要です:

??まず、いくつかの基本的なガイドラインを理解する必要があります:

1: zval の refcount が増加する場合、この zval はまだ使用されており、ゴミには属しません。

2: zval の refcount が 0 に減少すると、zval は解放され、ガベージになります。

3: zval の refcount が削減された後に 0 より大きい場合、zval は解放できず、zval はガベージになる可能性があります。

? ?基準 3 の場合にのみ、GC は zval を収集し、新しいアルゴリズムを使用して zval がガベージであるかどうかを判断します。では、そのような変数が本当にゴミであるかどうかを判断するにはどうすればよいでしょうか?簡単に言うと、zval の refcount が 0 の場合、zval の要素ごとに refcount が 1 ずつ減ります。この原理は非常に単純に見えますが、理解するのは簡単ではありません。構造図を通して理解してみましょう:

? GC アルゴリズムは、ガベージ判定のために呼び出されます。このアルゴリズムは、最初に前の基準 3 に該当するすべての zval ノードをノード (ルート) バッファー (ルート バッファー) に置き、同時にこれらの zval ノードを紫色にマークします。 、アルゴリズムは、各 zval ノードがバッファー内に 1 回出現することを保証する必要があります。バッファがノードでいっぱいになると、GC はバッファ内の zval ノードに対してガベージ判定を実行し始めます。

? ?B: バッファーがいっぱいになると、同じ zval の refcount が繰り返しデクリメントされないように、アルゴリズムは深さ優先で各ノードに含まれる zval を 1 つデクリメントします。 zval の refcount が 1 減ると、zval は灰色でマークされます。このステップでは、ノード zval 自体は最初は 1 ずつデクリメントされませんが、ノード zval に含まれる zval がノード zval (循環参照) を指している場合、ノード zval を 1 だけデクリメントする必要があることを強調しておく必要があります。現時点では。

? ?C: アルゴリズムは再び深さ優先で各ノードに含まれる zval の値を決定し、その refcount が 0 に等しい場合はそれを白としてマークします。 zval の が 0 より大きい場合、この zval とそれに含まれる zval の refcount が 1 だけ増加します。これは非ガベージの復元操作であり、同時にこれらの zval の色は黒に変更されます。 (zval のデフォルトの color 属性)

? ?D: zval ノードをトラバースし、C で白でマークされたノード zval を解放します。

2. ガベージ コレクション プロセスの詳細な説明と例実際の応用はどうでしょうか?以下は例を通して説明されます: ? ① 変数が宣言されて値が割り当てられたばかりのとき、それは実際には基準 1 と等価です (zval の refcount が増加しても、zval はまだ変化しません)。使用中であり、ガベージではありません)、変数はガベージではないため、GC チェックされません。

?②上記を踏まえて、unset()関数を呼び出して変数bとcを解放しました。次のように:

$a = "one";$b = array();$b[] = $a;$b[] = & $b;$c = "two";//声明了三个变量$a、$b、$c。这个时候refcount都是增加的情况,变量不是垃圾也不会放入到root缓冲器等待垃圾检查。xdebug_debug_zval( 'a' );  xdebug_debug_zval( 'b' );  xdebug_debug_zval( 'c' );  //输出分别如下:a: (refcount=2, is_ref=0)='one'b: (refcount=2, is_ref=1)=array (     0 => (refcount=2, is_ref=0)='one',     1 => (refcount=2, is_ref=1)=... )  c: (refcount=1, is_ref=0)='two'
?

?unset 関数を呼び出した後、$b と $c の対応するコンテナーの refcount は 1 ずつ減りますが、その効果は同じではありません。まず、unset ($c) を呼び出す $c を調べます。$c の refcount は 0 にプログラムされており、基準 2 に準拠します。次に、$c に対応する zval コンテナーはガベージであり、unset を呼び出した後に $b を調べます。 ($b) ですが、$b A 参照の最初の値は $b に対応する zval コンテナを指し続けますが、$b に対応する zval コンテナの refcount は 1 減らされ、値は 2 から に変わります。 1.このとき、コンテナの refcount は 1 減りますが、まだ 0 ではないため、基準 3 に適合し、$b に対応する zval がルート バッファに入れられます。 gc ガベージ チェック操作を待機しています。つまり、(2) の (A) の状況に入ります。

unset($b);unset($c);xdebug_debug_zval( 'a' ); //输出如下:a: (refcount=2, is_ref=0)='one'

? ③以降の動作は(2)のとおりです。 (2)のABCD処理を経ると、変数$bに対応するzvalコンテナが解放され、ガベージコレクションが完了し、循環参照のメモリリーク問題が解決されます。

3. ガベージコレクターの設定と使用

? PHP では、GC はデフォルトで有効になっています。ini ファイルの ?zend.enable_gc 項目を使用して GC を有効または無効にできます。 GC が有効な場合、ノード バッファ (ルート バッファ) がいっぱいになった後にガベージ分析アルゴリズムが開始されます。もちろん、バッファはデフォルトで 10,000 個の値を保持できます。PHP を再コンパイルしてリンクする必要があります。 GC がオフになると、ガベージ分析アルゴリズムは実行されませんが、この時点でバッファー ノードがいっぱいの場合、関連するノードはノード バッファーに置かれ、新しいノードは記録されません。記録されたノードはガベージ分析アルゴリズムによって分析されることはありません。これらのノードに循環参照がある場合、メモリ リークが発生する可能性があります。 GC がオフのときにこれらのノードを記録するのは、ノードが生成されるたびに GC がオンになっているかどうかを判断するよりも、単にこれらのノードを記録する方が高速であるためです。また、スクリプトの実行中に GC をオンにすることができます。したがって、これらのノードを記録します。コードの実行中のある時点で GC がオンになっている場合、これらのノードは分析アルゴリズムによって分析できます。もちろん、ガベージ分析アルゴリズムは比較的時間のかかる操作です。

??? PHP コードでは、gc_enable() 関数と gc_disable() 関数を使用して GC をオンまたはオフにすることができます。また、ノード バッファーがいっぱいでないときに gc_collect_cycles() を呼び出してガベージ分析を強制することもできます。 .アルゴリズム。このようにして、ユーザーはプログラムの特定の部分で GC をオフまたはオンにすることができ、ガベージ分析アルゴリズムを強制することもできます。 ?

?

?
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。