ホームページ  >  記事  >  バックエンド開発  >  php7のガベージコレクションの仕組みを詳しく解説

php7のガベージコレクションの仕組みを詳しく解説

藏色散人
藏色散人転載
2019-07-12 13:57:177865ブラウズ

php7のガベージコレクションの仕組みを詳しく解説

#php7 ガベージ コレクション メカニズムの詳細な説明

著者は数日前にこのトピックに興味を持ったので、ネットで検索したところ、ほとんどがphp 5のガベージコレクション機構に関するものでした。php5からphp7へのGC部分の変更は比較的小さいですが、やはり別途ブログ投稿する必要があると思います。特に明記されていない限り、PHP のバージョンは 7.2

です。PHP の変数によって占有されているスペースを手動で再利用する必要はありません。カーネルがこの部分の作業を処理します。 C と比較すると、これにより操作が大幅に容易になります。

この記事では主に変数の GC メカニズムについて説明します

php GC を理解する場合、php 変数の基礎となる実装を紹介する必要があると感じます。

zvalの構造

// php 变量对于的c结构体
struct _zval_struct {
    zend_value value;
    union {
       ……
    } u1;
    union {
        ……
    } u2;
};

主にガベージコレクションの話なので、u1 u2 Unionの機能を簡単に紹介します

u1 の構造はさらに複雑で、主に変数の型を識別するために使用されると思います。

u2 それらのほとんどは補助フィールド、変数の内部関数の実装、キャッシュの使いやすさの向上などです。

次が主人公です

zend_value これも構造体

typedef union _zend_value {
    zend_long         lval;//整形
    double            dval;//浮点型
    zend_refcounted  *counted;//获取不同类型的gc头部
    zend_string      *str;//string字符串
    zend_array       *arr;//数组
    zend_object      *obj;//对象
    zend_resource    *res;//资源
    zend_reference   *ref;//是否是引用类型
  
    // 忽略下面的结构,与我们讨论无关
    zend_ast_ref     *ast;
    zval             *zv;
    void             *ptr;
    zend_class_entry *ce;
    zend_function    *func;
    struct {
        ZEND_ENDIAN_LOHI(
            uint32_t w1,
            uint32_t w2)
    } ww;
} zend_value;

に埋め込まれた共用体です 参照カウント zend_refcounted *counted 型は zval の値に記録され、ガベージ コレクション メカニズムもこれに基づいて。

typedef struct _zend_refcounted_h {
    uint32_t         refcount;          /* reference counter 32-bit */
    union {
        struct {
            ZEND_ENDIAN_LOHI_3(
                zend_uchar    type,
                zend_uchar    flags,    /* used for strings & objects */
                uint16_t      gc_info)  /* keeps GC root number (or 0) and color */
        } v;
        uint32_t type_info;
    } u;
} zend_refcounted_h;

すべての複合型定義は zend_refcounted_h 構造体で始まります。参照カウントに加えて、この構造体には GC 関連の構造体もあります。したがって、GC リサイクルを行うとき、GC は詳細を気にする必要はありません。型とは何ですか? それらはすべて zend_refcounted* 構造体として扱うことができます。

変数の自動リサイクル

PHP では、配列型変数とオブジェクト型変数を除き、ほとんどの変数は自動的にリサイクルされます

php. 通常の変数のリサイクルは、変数への参照の数に関係します。

公式例

$a = 1;
$b = $a;
xdebug_debug_zval('a');
$a =10;
xdebug_debug_zval('a');
unset($a);
xdebug_debug_zval('a');

結果

a:
(refcount=2, is_ref=0),int 1
a:
(refcount=1, is_ref=0),int 10
a: no such symbol

$a =10の場合、phpのCOW(コピーオンライト)機構が関与していることがわかります、$b元の$aのコピーがコピーされ、両者の参照関係が解除されるため、aの参照数(refcount)が1になります。

そして、uset($a) を実行すると、a への参照の数は 0 になります。これはガベージ変数とみなされ、スペースが解放されます。

例を挙げてください

$a = [1];
$a[1] = &$a;
unset($a);

unset($a) 前の $a の型は参照型です

a:
(refcount=2, is_ref=1),
array (size=2)
  0 => (refcount=1, is_ref=0),int 1
  1 => (refcount=2, is_ref=1),
    &array<

php7のガベージコレクションの仕組みを詳しく解説

unset($ a) その後、次のようになります。

php7のガベージコレクションの仕組みを詳しく解説

このとき、unsetすると、$aを指す内部参照があるため、refcountが2から1に変わります。したがって、外部にある占有空間は破壊されません。

その後、外部参照が中断され、使用できなくなりました。 C言語でワイルドポインタと呼ばれる「オーファン」となります。 phpでは循環参照といいます。メモリーリーク。変数を破棄したい場合は、php スクリプトが終了するまで待つだけです。

循環参照によって引き起こされるメモリ リーク

これらのゴミをクリーンアップするために、2 つの基準が導入されます

# 参照カウントが減少した場合ゼロ、コンテナが配置されている変数 コンテナはクリア (解放) され、ガベージではありません

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

循環参照は基本的に配列とオブジェクトにのみ現れます。オブジェクトはそれ自体が参照であるためです。

オブジェクトと配列のリサイクル プロセス

php7 のガベージ コレクションは 2 つの部分で構成されており、1 つはガベージ コレクターで、もう 1 つはガベージ コレクション アルゴリズムです。

ガベージ コレクターは、ゴミの可能性がある前述の要素をリサイクル プールに収集します。つまり、変数の zend_refcount 情報がリサイクル プールに配置されます。リサイクルプールの価値が一定量に達すると一律に処理されます。

処理プロセスは比較的単純です。

リサイクル プール内のすべての変数を走査し、各変数に基づいて各メンバーを走査します。メンバーがまだネストされている場合は、走査を続けます。次に、すべてのメンバーのシミュレートされた refcount を -1 に設定します。このとき外部変数の参照回数が0の場合。そうすれば、それは明らかにゴミとみなされます。 0 より大きい場合、参照の数は復元され、ガベージ コレクション プールから取り出されます。

ガベージ コレクションの原理

変数がガベージではない場合、そのすべてのメンバー変数の参照が 1 つ減らされた後、合計変数の参照が減らされます。絶対に0にはなりません。

言うのはかなり難しいので、例を挙げてみましょう。初めて sf.gg を閲覧したときに GC に関する質問を見つけたので、それに答えました。 GC ガベージ コレクションのメカニズムについて

トピックは次のとおりです

php7のガベージコレクションの仕組みを詳しく解説

//我的回答
1、只要zval.value的refcount减一,然后缺其refcount的值不为0那么它就可能是垃圾,进入垃圾周期。
2、进入垃圾池遍历所有成员,包括其嵌套的成员,都对其做 refcount-1的操作,看外部的引用是否为0。
那么对于 题主的问题来说,
首先,你要想$a为垃圾,一定要先对 unset($a)操作,那么此时 $a的 refcount = 2
对于$a[0] refcount-1 不影响外部的$a,
$a[1] refcount-1 ,此时 $a的 refount=1
$a[2] refcount-1 ,此时 $a 的 refount=0 
模拟减结束,那么此变量被当成垃圾回收。

以上がphp7のガベージコレクションの仕組みを詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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