Heim Backend-Entwicklung PHP7 PHP7 erklärt den Garbage-Collection-Mechanismus

PHP7 erklärt den Garbage-Collection-Mechanismus

Mar 11, 2021 am 09:32 AM
php7 垃圾回收机制

Der Autor hat sich vor ein paar Tagen für dieses Thema interessiert, also habe ich online gesucht und festgestellt, dass es sich bei fast allen um den Garbage-Collection-Mechanismus von PHP 5 handelt. Obwohl die im GC-Teil von PHP5 zu PHP7 vorgenommenen Änderungen relativ gering sind, Ich denke, es ist immer noch notwendig, den Blogbeitrag separat zu veröffentlichen. Wenn nicht ausdrücklich angegeben, ist die PHP-Version 7.2

Der von Variablen in PHP belegte Speicherplatz erfordert nicht, dass wir ihn manuell zurückfordern. Der Kernel übernimmt diesen Teil der Arbeit für uns. Im Vergleich zu C erleichtert dies unsere Bedienung erheblich.

Dieser Artikel erklärt hauptsächlich den GC-Mechanismus von Variablen.

PHP7 erklärt den Garbage-Collection-Mechanismus

Artikelverzeichnis Sammlung

Beispiel
  • Empfohlen (kostenlos):
  • PHP7
    • Um unseren PHP-GC zu verstehen, halte ich es für notwendig, die zugrunde liegende Implementierung unserer PHP-Variablen vorzustellen.
    • zval-Struktur
// php 变量对于的c结构体
struct _zval_struct {
    zend_value value;
    union {
       ……
    } u1;
    union {
        ……
    } u2;
};
Nach dem Login kopieren
Da es hauptsächlich um Garbage Collection geht, hier eine kurze Einführung in die Funktion von u1 u2 Union

u1 Die Struktur ist meiner Meinung nach relativ komplex um Variablentypen zu identifizieren u2 Die meisten davon sind Hilfsfelder, Implementierung interner Funktionen von Variablen, Verbesserung der Cache-Freundlichkeit usw. Als nächstes kommt unser Protagonist zend_value Es ist auch eine Struktur. Eine in

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;
Nach dem Login kopieren
eingebettete Union zeichnet den Typ des Referenzzählers zend_refcounted *counted im Wert von zval auf. Auch unser Garbage-Collection-Mechanismus basiert darauf.

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;
Nach dem Login kopieren
Alle komplexen Typdefinitionen beginnen mit der Struktur zend_refcounted_h. Zusätzlich zur Referenzzählung verfügt diese Struktur auch über GC-bezogene Strukturen. Daher muss sich der GC nicht darum kümmern über den spezifischen Typ, die alle als zend_refcounted*-Struktur verarbeitet werden können. #Automatisches Recycling von Variablen

In PHP, außer array und Die meisten der Variablen vom Typ object werden automatisch recycelt. PHP Das Recycling gewöhnlicher Variablen hängt von der Anzahl der Verweise auf die Variable ab.
u1 结构比较复杂,我认为主要是用于识别变量类型
u2 这里面大多都是辅助字段,变量内部功能的实现、提升缓存友好性等等
接下来是我们的主角

zend_value 它也是结构体中内嵌的一个联合体

$a = 1;
$b = $a;
xdebug_debug_zval('a');
$a =10;
xdebug_debug_zval('a');
unset($a);
xdebug_debug_zval('a');
Nach dem Login kopieren

zval的 value中就记录了引用计数zend_refcounted *counted这个类型,我们的垃圾回收机制也是基于此的。

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

所有的复杂类型的定义, 开始的时候都是zend_refcounted_h结构, 这个结构里除了引用计数以外, 还有GC相关的结构. 从而在做GC回收的时候, GC不需要关心具体类型是什么, 所有的它都可以当做zend_refcounted*结构来处理.
#变量的自动回收

在php中 除了 arrayobject类型的变量,其余大部分是自动回收
php 普通变量的回收和 该变量的引用次数有关。

官方的例子

$a = [1];
$a[1] = &$a;
unset($a);
Nach dem Login kopieren

结果

a:
(refcount=2, is_ref=1),
array (size=2)
  0 => (refcount=1, is_ref=0),int 1
  1 => (refcount=2, is_ref=1),
    &array<p>可以看到 当<code>$a =10</code> 的时候 涉及到 php的COW(copy-on-write)机制,$b 会复制一份原先的 $a ,解除了他们之间的引用关系,所以a的引用次数(refcount)减少为1。</p><p>然后我们uset($a)之后 a的引用次数变为0。这就会被认为是垃圾变量,释放空间。</p><p>在举一个例子</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">//我的回答
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 
模拟减结束,那么此变量被当成垃圾回收。
Nach dem Login kopieren
Nach dem Login kopieren

在 unset($a) 之前 $a 的类型为引用类型

rrreee

unset($a) 之后,就变成这样

这时候,我们unset操作时refcount 由2变为1,因为有内部引用指向 $a,所以在外部 其所占用的空间并不会被销毁。

然后我们的外部引用已经被中断了,我们也不能使用它。它就成了一个“孤儿”,在c语言中叫做野指针。在php中叫做循环引用。内存泄漏。想要销毁变量的话,只能等 php脚本结束。

循环引用造成的内存泄漏

为了清理这些垃圾,引入了两个准则

  • 如果引用计数减少到零,所在变量容器将被清除(free),不属于垃圾
  • 如果一个zval 的引用计数减少后还大于0,那么它会进入垃圾周期。其次,在一个垃圾周期中,通过检查引用计数是否减1,并且检查哪些变量容器的引用次数是零,来发现哪部分是垃圾。

循环引用基本上只会出现在 数组和对象中,对象是因为它的本身就是引用

object和array的回收过程

php7的垃圾回收包含两个部分,一个是垃圾收集器,一个是垃圾回收算法。

垃圾收集器,把刚刚提到的,可能是垃圾的元素收集到回收池中 也就是把变量的 zend_refcount>0的变量 放在回收池中。 当回收池的值达到一定额度了,会进行统一遍历处理。进行模拟删除,如果zend_refcount=0Offizielles Beispiel

rrreee

Ergebnis

rrreee

Sie können sehen, dass $b das Original von $a kopiert, wenn $a =10 den COW-Mechanismus (Copy-on-Write) von PHP verwendet , wird die Referenzbeziehung zwischen ihnen freigegeben, 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.

Geben Sie ein Beispiel

rrreee

Der Typ von $a vor unset($a) ist ein Referenztyprrreee

🎜unset($a) Danach sieht es so aus🎜🎜PHP7 erklärt den Garbage-Collection-Mechanismus
//我的回答
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 
模拟减结束,那么此变量被当成垃圾回收。
Nach dem Login kopieren

更多免费学习推荐:PHP7教程

Das obige ist der detaillierte Inhalt vonPHP7 erklärt den Garbage-Collection-Mechanismus. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

So lösen Sie das Problem, wenn PHP7 erkennt, dass der TCP-Port nicht funktioniert So lösen Sie das Problem, wenn PHP7 erkennt, dass der TCP-Port nicht funktioniert Mar 22, 2023 am 09:30 AM

In PHP5 können wir die Funktion fsockopen() verwenden, um den TCP-Port zu erkennen. Mit dieser Funktion können Sie eine Netzwerkverbindung herstellen und eine Netzwerkkommunikation durchführen. In PHP7 kann die Funktion fsockopen() jedoch auf einige Probleme stoßen, z. B. dass der Port nicht geöffnet werden kann, keine Verbindung zum Server hergestellt werden kann usw. Um dieses Problem zu lösen, können wir die Funktionen socket_create() und socket_connect() verwenden, um den TCP-Port zu erkennen.

So installieren Sie die Mongo-Erweiterung in PHP7.0 So installieren Sie die Mongo-Erweiterung in PHP7.0 Nov 21, 2022 am 10:25 AM

So installieren Sie die Mongo-Erweiterung in PHP7.0: 1. Erstellen Sie die Mongodb-Benutzergruppe und den Mongodb-Benutzer. 2. Laden Sie das Mongodb-Quellcodepaket herunter und platzieren Sie das Quellcodepaket im Verzeichnis „/usr/local/src/“. Geben Sie das Verzeichnis „src/“ ein. 4. Entpacken Sie das Quellcodepaket. 6. Kopieren Sie die Dateien in das Verzeichnis „mongodb/“.

Was soll ich tun, wenn das Plug-in in php7.0 installiert ist, aber immer noch angezeigt wird, dass es nicht installiert ist? Was soll ich tun, wenn das Plug-in in php7.0 installiert ist, aber immer noch angezeigt wird, dass es nicht installiert ist? Apr 02, 2024 pm 07:39 PM

So beheben Sie das Problem, dass das Plugin in PHP 7.0 nicht installiert ist: Überprüfen Sie die Plugin-Konfiguration und aktivieren Sie das Plugin. Starten Sie PHP neu, um die Konfigurationsänderungen zu übernehmen. Überprüfen Sie die Berechtigungen der Plugin-Datei, um sicherzustellen, dass sie korrekt sind. Installieren Sie fehlende Abhängigkeiten, um sicherzustellen, dass das Plugin ordnungsgemäß funktioniert. Wenn alle anderen Schritte fehlschlagen, erstellen Sie PHP neu. Weitere mögliche Ursachen sind inkompatible Plugin-Versionen, das Laden der falschen Version oder PHP-Konfigurationsprobleme.

Ein Artikel über den Garbage-Collection-Mechanismus in PHP Ein Artikel über den Garbage-Collection-Mechanismus in PHP Aug 26, 2022 am 10:48 AM

Dieser Artikel wird Ihnen ein tiefgreifendes Verständnis des Garbage-Collection-Mechanismus in PHP vermitteln. Ich hoffe, er wird Ihnen hilfreich sein!

So installieren und implementieren Sie PHP7.0 So installieren und implementieren Sie PHP7.0 Nov 30, 2022 am 09:56 AM

So installieren und implementieren Sie PHP7.0: 1. Gehen Sie zur offiziellen PHP-Website, um die dem lokalen System entsprechende Installationsversion herunterzuladen. 2. Extrahieren Sie die heruntergeladene ZIP-Datei in das angegebene Verzeichnis. 3. Öffnen Sie das Befehlszeilenfenster und gehen Sie zu das Verzeichnis „E:\php7“ Führen Sie einfach den Befehl „php -v“ aus.

FAQ-Leitfaden zur PHP-Serverumgebung: Häufige Probleme schnell lösen FAQ-Leitfaden zur PHP-Serverumgebung: Häufige Probleme schnell lösen Apr 09, 2024 pm 01:33 PM

Zu den gängigen Lösungen für PHP-Serverumgebungen gehört die Sicherstellung, dass die richtige PHP-Version installiert ist und relevante Dateien in das Modulverzeichnis kopiert wurden. Deaktivieren Sie SELinux vorübergehend oder dauerhaft. Überprüfen und konfigurieren Sie PHP.ini, um sicherzustellen, dass die erforderlichen Erweiterungen hinzugefügt und korrekt eingerichtet wurden. Starten oder starten Sie den PHP-FPM-Dienst neu. Überprüfen Sie die DNS-Einstellungen auf Auflösungsprobleme.

Entschlüsselung des Speicherverwaltungs- und Garbage-Collection-Mechanismus der Go-Sprache Entschlüsselung des Speicherverwaltungs- und Garbage-Collection-Mechanismus der Go-Sprache Nov 30, 2023 am 09:17 AM

Die Go-Sprache ist eine effiziente, sichere und gleichzeitige Programmiersprache. Das Design des Speicherverwaltungs- und Garbage-Collection-Mechanismus ist ebenfalls ein einzigartiges Merkmal. In diesem Artikel werden die Speicherverwaltungs- und Speicherbereinigungsmechanismen der Go-Sprache ausführlich entschlüsselt. 1. Speicherverwaltung In der Go-Sprache umfasst die Speicherverwaltung zwei Aspekte: Speicherzuweisung und Speicherfreigabe. 1.1 Speicherzuweisung In der Go-Sprache weisen wir Speicher über die integrierten Funktionen new und make zu. Unter anderem gibt new einen Zeiger auf den neu zugewiesenen Nullwert zurück, während make einen angegebenen Typ und seine Länge zurückgibt.

Was ist besser, PHP8 oder PHP7? Was ist besser, PHP8 oder PHP7? Nov 16, 2023 pm 03:09 PM

Im Vergleich zu PHP7 bietet PHP8 einige Vorteile und Verbesserungen in Bezug auf Leistung, neue Funktionen und Syntaxverbesserungen, Typsystem, Fehlerbehandlung und Erweiterungen. Die Wahl der zu verwendenden Version hängt jedoch von Ihren spezifischen Anforderungen und Projektumständen ab. Detaillierte Einführung: 1. Leistungsverbesserung: PHP8 führt den Just-in-Time-Compiler (JIT) ein, der die Ausführungsgeschwindigkeit des Codes verbessern kann. 2. Neue Funktionen und Syntaxverbesserungen. PHP8 unterstützt die Deklaration benannter Parameter und optionaler Parameter. Durch die flexiblere Gestaltung von Funktionen werden anonyme Klassen, Typdeklarationen von Eigenschaften usw. eingeführt.

See all articles