ホームページ  >  記事  >  バックエンド開発  >  PHP の基本原理のガベージ コレクション メカニズムの紹介 (コード例)

PHP の基本原理のガベージ コレクション メカニズムの紹介 (コード例)

不言
不言転載
2019-03-04 14:34:302601ブラウズ

この記事は、PHP の基本原理のガベージ コレクション メカニズム (コード例) を紹介するものです。一定の参考価値があります。必要な友人は参照してください。お役に立てば幸いです。 。

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;
        zend_ast *ast;
    } 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');
Result:

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 はすぐには生成されません。代わりに、変数 b は、変数 a が指す変数コンテナ、つまりメモリを指します。共有"; そして変数 b の 1 つの要素が変更されると、変数コンテナのコピーが実際に発生します。これは

コピーオンライト テクノロジです。

参照カウントは 0

## にクリアされます。 #変数コンテナの ref_count が 0 にクリアされると、変数コンテナが破棄されることを意味し、メモリの再利用が実現します。これも

php5.3 より前のバージョンのガベージ コレクション機構です

#例:

$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)='许铮的技术成长之路'
循環参照によるメモリ リーク問題

しかし、php5.3 より前のガベージ コレクション メカニズムには抜け穴があります。配列またはオブジェクト内の子要素はその親要素を参照しており、この時点で親要素が削除されても、変数コンテナは削除されません。その子要素は依然として変数コンテナを指していますが、変数コンテナが存在しないため、変数コンテナは削除されません。どのスコープでも変数コンテナを指すシンボルはクリアできないため、スクリプトの実行が終了するまでメモリリークが発生します。

Example:

$a = array( 'one' );
$a[] = &$a;
xdebug_debug_zval( 'a' );
この例は出力するのが簡単ではないため、これは、次の図に示すように図で表されます。


##例:

unset($a);
xdebug_debug_zval('a');
PHP の基本原理のガベージ コレクション メカニズムの紹介 (コード例)図に示すように :


新しいガベージ コレクション メカニズム

PHP の基本原理のガベージ コレクション メカニズムの紹介 (コード例)ルート バッファリング メカニズムはバージョン php5.3 以降に導入されました。つまり、PHP が Root を開始するときに指定された zval 番号がデフォルト設定になります。バッファ (デフォルトは 10000) の場合、循環参照を持つ zval があることを PHP が検出すると、ルート バッファに配置され、ルート バッファが設定ファイルで指定された数 (デフォルトは 10000) に達すると、実行されます。循環参照によるメモリ リーク問題を解決するためのガベージ コレクション

ガベージ確認のガイドライン

1. 参照カウントがゼロになると、変数コンテナはクリア (解放) されますが、そうではありません。ガベージ

2. zval の参照カウントが削減された後も 0 より大きい場合、ガベージ サイクルに入ります。次に、ガベージ サイクル中に、参照カウントが 1 減らされているかどうかを確認し、どの変数コンテナの参照が 0 であるかを確認して、どの部分がガベージであるかを見つけます。

概要


ガベージ コレクション メカニズム:

1. PHP の参照カウント メカニズムに基づく (PHP5.3 より前ではこのメカニズムのみが利用可能でした)

2. 次のルート バッファ メカニズムを使用します。同時に、PHP は循環参照のある zval があることを検出すると、それをルート バッファーに配置します。ルート バッファーが設定ファイルで指定された数に達すると、ガベージ コレクションが実行されて、循環参照によるメモリ リークを解決します。循環参照 問題 (php5.3 でこのメカニズムが導入され始めました)


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

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