php のガベージ コレクション メカニズムは、PHPer にとってよく知られていますが、あまり馴染みのない内容です。では、PHP はどのようにして不要なメモリをリサイクルするのでしょうか?
php 変数のメモリ格納構造:
まず、ガベージ コレクションの原理を理解しやすくするための基礎知識を理解する必要があります。 PHP が C で書かれていることは誰もが知っているので、PHP 変数の内部ストレージ構造も C 言語、つまり zval の構造に関連します。
struct _zval_struct { union { long lval; double dval; struct { char *val; int len; } str; HashTable *ht; zend_object_value obj; } value; //变量value值 zend_uint refcount__gc; //引用计数内存中使用次数,为0删除该变量 zend_uchar type; //变量类型 zend_uchar is_ref__gc; //区分是否是引用变量 };
の内容からわかります。各php変数は、変数の型、値の値、参照カウント数、参照変数かどうかの4つの部分で構成される上記の構造です。
注: 上記のzval構造は、php5.3バージョン以降の構造です。 php5.3 より前では、新しいものは導入されておらず、ガベージ コレクション メカニズムは GC であるため、名前は _gc
; ではなく、PHP7 バージョン以降は、パフォーマンスの問題により zval 構造体が書き換えられたため、ここでは説明しません。
参照カウントの原則:
PHP 変数の内部ストレージ構造を理解した後、PHP 変数の割り当てと初期のガベージ コレクション メカニズムに関連する原則について学びます。
変数コンテナ
非配列変数とオブジェクト変数
定数が変数に代入されるたびに、変数コンテナが生成されます。
例:
$a = '许铮的技术成长之路'; xdebug_debug_zval('a')
結果:
a: (refcount=1, is_ref=0)='许铮的技术成长之路'
配列変数とオブジェクト変数
は要素番号を生成します番号 1 の変数コンテナ
例:
$b = [ 'name' => '许铮的技术成长之路', 'number' => 3 ]; xdebug_debug_zval('b')
結果:
b: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='许铮的技术成长之路', 'number' => (refcount=1, is_ref=0)=3)
代入原則 (コピーオンライト テクノロジ)
定数の代入を理解したら、メモリの観点から変数間の代入を考えてみましょう
例:
$a = [ 'name' => '许铮的技术成长之路', 'number' => 3 ]; //创建一个变量容器,变量a指向给变量容器,a的ref_count为1 $b = $a; //变量b也指向变量a指向的变量容器,a和b的ref_count为2 xdebug_debug_zval('a', 'b'); $b['name'] = '许铮的技术成长之路1';//变量b的其中一个元素发生改变,此时会复制出一个新的变量容器, 变量b重新指向新的变量容器,a和b的ref_count变成1 xdebug_debug_zval('a', 'b');
結果:
a: (refcount=2, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='许铮的技术成长之路', 'number' => (refcount=1, is_ref=0)=3) b: (refcount=2, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='许铮的技术成长之路', 'number' => (refcount=1, is_ref=0)=3) a: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='许铮的技术成长之路', 'number' => (refcount=1, is_ref=0)=3) b: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='许铮的技术成长之路1', 'number' => (refcount=1, is_ref=0)=3)
つまり、変数 a が変数 b に代入されるとき、新しい変数コンテナはすぐには生成されませんが、変数 b は変数 a が指す変数コンテナを指します、つまり、メモリが「共有」されます。これは Copy on writeTechnology
参照カウントは 0
$a = "许铮的技术成长之路"; $b = $a; xdebug_debug_zval('a'); unset($b); xdebug_debug_zval('a');結果:
a: (refcount=2, is_ref=0)='许铮的技术成长之路' a: (refcount=1, is_ref=0)='许铮的技术成长之路'
循環参照によるメモリ リークの問題:
$a = array( 'one' ); $a[] = &$a; xdebug_debug_zval( 'a' );この例では出力が適切ではないため、次の図に示すようにグラフィカル表現を使用します。 例:
unset($a); xdebug_debug_zval('a');図に示すように:
ガベージであることを確認する基準:
1. 参照カウントがゼロに減らされた場合、変数コンテナはクリア (解放) され、ガベージではなくなります。2. zval の参照カウントが減らされても、依然として より大きい場合0 の場合、ガベージ サイクルに入ります。次に、ガベージ サイクル中に、参照カウントが 1 減らされているかどうかを確認し、どの変数コンテナの参照が 0 であるかを確認して、どの部分がガベージであるかを見つけます。
概要:
ガベージ コレクション メカニズム:1. php の参照カウント メカニズムに基づいています (php5.3 より前ではこのメカニズムのみが利用可能でした)
2 、ルート バッファ メカニズムを同時に使用します。PHP は、循環参照を持つ zval があることを検出すると、それをルート バッファに置きます。ルート バッファが設定ファイルで指定された数に達すると、ガベージ コレクションが実行されます。循環参照によって引き起こされるメモリ リークの問題を解決する (php5.3 でこのメカニズムが導入され始めました)
以上がPHP ガベージ コレクションの原理を 10 分で理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。