ホームページ  >  記事  >  バックエンド開発  >  php7でガベージコレクション機構を実装する方法

php7でガベージコレクション機構を実装する方法

醉折花枝作酒筹
醉折花枝作酒筹転載
2021-05-24 09:21:221870ブラウズ

この記事では、php7 がガベージ コレクション メカニズムを実装する方法を紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。

php7でガベージコレクション機構を実装する方法

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 *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<

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

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

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

循環参照によるメモリ リーク

これらのガベージをクリーンアップするために、2 つのガイドラインが導入されています

  • 参照カウントがゼロになった場合、変数コンテナはクリア (無料) され、ガベージではありません

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

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

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

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

ガベージ コレクターは、ガベージである可能性がある前述の要素をリサイクル プールに収集します。つまり、zend_refcount>0 の変数がリサイクル プールに配置されます。リサイクル プールの値が一定の量に達すると、均一に走査されます。シミュレートされた削除を実行します。zend_refcount=0 の場合、ゴミとみなされ、直接削除されます。

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

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

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

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

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


//我的回答
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 ビデオ チュートリアル

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

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