Heim > Artikel > Backend-Entwicklung > So implementieren Sie den Garbage-Collection-Mechanismus in PHP7
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.
Wenn ich unseren PHP-GC verstehe, halte ich es für notwendig, die zugrunde liegende Implementierung unserer PHP-Variablen vorzustellen.
// 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.
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 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
Beispiel
//我的回答 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-Tutorial
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!