Heim >Backend-Entwicklung >PHP7 >So implementieren Sie den Garbage-Collection-Mechanismus in PHP7

So implementieren Sie den Garbage-Collection-Mechanismus in PHP7

醉折花枝作酒筹
醉折花枝作酒筹nach vorne
2021-05-24 09:21:221926Durchsuche

In diesem Artikel erfahren Sie, wie Sie den Garbage-Collection-Mechanismus in PHP7 implementieren. Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird für alle hilfreich sein.

So implementieren Sie den Garbage-Collection-Mechanismus in PHP7

Wenn ich unseren PHP-GC verstehe, halte ich es für notwendig, die zugrunde liegende Implementierung unserer PHP-Variablen vorzustellen.

Die Struktur von zval

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

Da es hauptsächlich um die Speicherbereinigung geht, finden Sie hier eine kurze Einführung in die Funktionen der u1 u2-Union
u1 Die Struktur ist relativ komplex, ich denke, sie wird hauptsächlich zur Identifizierung von Variablentypen verwendet
u2 Die meisten davon sind Hilfsfelder, die Implementierung interner Funktionen von Variablen, die Verbesserung der Cache-Freundlichkeit usw.
Als nächstes kommt unser Protagonist

zend_value Es ist auch eine in die Struktur eingebettete Union

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;

Der Referenzzähler zend_refcounted *counted wird in aufgezeichnet der Wert von zval Dieser Typ basiert auch auf unserem Garbage-Collection-Mechanismus.

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;

Alle komplexen Typdefinitionen beginnen mit der Struktur zend_refcounted_h. Diese Struktur verfügt daher auch über GC-bezogene Strukturen. Daher muss sich der GC beim GC-Recycling nicht um den jeweiligen Typ kümmern können als zend_refcounted*-Strukturen verarbeitet werden.
#Automatisches Recycling von Variablen

Mit Ausnahme von Array- und Objekttypvariablen in PHP werden die meisten anderen automatisch recycelt
PHP Das Recycling gewöhnlicher Variablen hängt von der Anzahl der Verweise auf die Variable ab .

Offizielles Beispiel

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

Das Ergebnis

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

Sie können sehen, dass, wenn $a = 10 den COW-Mechanismus (Copy-on-Write) von PHP beinhaltet, $b das ursprüngliche $a kopiert und diese beseitigt. Die Referenzbeziehung zwischen a, sodass die Anzahl der Referenzen (Refcount) von a auf 1 reduziert wird.

Nachdem wir t($a) verwendet haben, wird die Anzahl der Verweise auf a zu 0. Dies wird als Müllvariable betrachtet und gibt Speicherplatz frei.

Ein weiteres Beispiel

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

Vor unset($a) ist der Typ von $a ein Referenztyp

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) Danach sieht es so aus

Zu diesem Zeitpunkt wir unset Während des Betriebs ändert sich refcount von 2 auf 1. Da es eine interne Referenz gibt, die auf $a zeigt, wird der von ihr belegte Speicherplatz nicht extern zerstört.

Dann ist unser Außenbezug kaputt und wir können ihn nicht nutzen. Es wird zu einem „Waise“, was in der C-Sprache als Wild-Zeiger bezeichnet wird. In PHP nennt man das einen Zirkelverweis. Speicherleck. Wenn Sie die Variable zerstören möchten, können Sie nur warten, bis das PHP-Skript beendet ist.

Speicherlecks durch Zirkelverweise

Um diesen Müll zu beseitigen, werden zwei Richtlinien eingeführt

  • Wenn der Referenzzähler auf Null reduziert wird, wird der Variablencontainer gelöscht (frei), was kein Müll ist

  • Wenn der Referenzzähler von zval reduziert wird und immer noch größer als 0 ist, gelangt er in den Müllkreislauf. Zweitens können Sie während eines Garbage-Zyklus herausfinden, welche Teile Garbage sind, indem Sie prüfen, ob die Referenzanzahl um 1 reduziert wird und welche Variablencontainer keine Referenzen haben.

Zirkuläre Referenzen erscheinen grundsätzlich nur in Arrays und Objekten. Das Objekt ist, weil es selbst eine Referenz ist.

Der Recyclingprozess von Objekten und Arrays. Die Garbage Collection von PHP7 besteht aus zwei Teilen, einem ist der Garbage Collector und einem ist der Garbage-Collection-Algorithmus.

Der Garbage Collector sammelt die gerade erwähnten Elemente, die möglicherweise Müll sind, im Recyclingpool, dh er legt die Variablen mit zend_refcount>0 im Recyclingpool ab. Wenn der Wert des Recyclingpools einen bestimmten Betrag erreicht, wird er gleichmäßig durchlaufen. Führen Sie eine simulierte Löschung durch. Wenn zend_refcount=0 ist, wird es als Müll betrachtet und direkt gelöscht.

Durchlaufen Sie jede Variable im Recycling-Pool und dann jedes Mitglied basierend auf jeder Variablen. Wenn die Mitglieder noch verschachtelt sind, fahren Sie mit dem Durchlaufen fort. Setzen Sie dann den simulierten Refcount aller Mitglieder auf -1. Wenn der Referenzzähler der externen Variablen zu diesem Zeitpunkt 0 ist. Dann kann es eindeutig als Müll betrachtet werden. Wenn er größer als 0 ist, wird die Anzahl der Referenzen wiederhergestellt und aus dem Garbage Collection-Pool entfernt.

Das Prinzip der Garbage Collection

Wenn Ihre Variable kein Müll ist, werden die gesamten Variablenreferenzen definitiv nicht 0 sein, nachdem die Referenzen aller ihrer Mitgliedsvariablen um eins reduziert wurden.

Beispiel

Es ist ziemlich schwer zu erklären, also geben wir ein Beispiel. Als ich sf.gg zum ersten Mal durchsuchte, sah ich eine Frage zu GC und beantwortete sie. In Bezug auf den GC-Garbage-Collection-Mechanismus lautet das Thema wie folgt:

//我的回答
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 
模拟减结束,那么此变量被当成垃圾回收。

Empfohlenes Lernen:
php-Video-TutorialSo implementieren Sie den Garbage-Collection-Mechanismus in PHP7

Das obige ist der detaillierte Inhalt vonSo implementieren Sie den Garbage-Collection-Mechanismus in PHP7. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen