Maison > développement back-end > PHP7 > le corps du texte

Explication détaillée du mécanisme de récupération de place de PHP7

藏色散人
Libérer: 2023-02-17 12:32:01
avant
8005 Les gens l'ont consulté

Explication détaillée du mécanisme de récupération de place de PHP7

Explication détaillée du mécanisme de récupération de place de php7

L'auteur s'est intéressé à ce sujet il y a quelques jours, donc J'ai cherché en ligne, presque tous sont le mécanisme de récupération de place de php 5. Bien que les modifications apportées dans la partie GC de php5 à php7 soient relativement faibles, je pense qu'il est toujours nécessaire de rédiger un article de blog séparé. Sauf indication contraire, la version PHP est 7.2

. L'espace occupé par les variables en PHP n'a pas besoin d'être récupéré manuellement. Le noyau gère cette partie du travail pour nous. Par rapport au C, cela facilite grandement notre fonctionnement.

Cet article explique principalement le mécanisme GC des variables

Lors de la compréhension de notre GC php, je pense qu'il est nécessaire d'introduire l'implémentation sous-jacente de nos variables php.

La structure de zval

// php 变量对于的c结构体
struct _zval_struct {
    zend_value value;
    union {
       ……
    } u1;
    union {
        ……
    } u2;
};
Copier après la connexion

Puisqu'il parle principalement de garbage collection, voici une brève introduction aux fonctions de u1 u2 union

Le La structure de u1 est plus compliquée , Je pense qu'elle est principalement utilisée pour identifier les types de variables

u2 La plupart d'entre eux sont des champs auxiliaires, la mise en œuvre de fonctions internes des variables, l'amélioration de la convivialité du cache, etc.

Ensuite est notre protagoniste

zend_value C'est aussi une union intégrée dans la structure

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;
Copier après la connexion

Le type de compteur de références zend_refcounted *counted est enregistré dans la valeur de zval. basé sur cela.

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;
Copier après la connexion

Toutes les définitions de types complexes commencent par la structure zend_refcounted_h En plus du comptage de références, cette structure a également des structures liées au GC. Par conséquent, lors du recyclage du GC, le GC n'a pas besoin de se soucier des détails. Quel est le type ? Toutes peuvent être traitées comme des structures zend_refcounted*.

Recyclage automatique des variables

En plus des variables de type tableau et objet en php, le rest La plupart d'entre elles sont automatiquement recyclées

php Le recyclage des variables ordinaires est lié au nombre de références à la variable.

Exemple officiel

$a = 1;
$b = $a;
xdebug_debug_zval('a');
$a =10;
xdebug_debug_zval('a');
unset($a);
xdebug_debug_zval('a');
Copier après la connexion

Résultat

a:
(refcount=2, is_ref=0),int 1
a:
(refcount=1, is_ref=0),int 10
a: no such symbol
Copier après la connexion

Vous pouvez voir que lorsque $a =10, le mécanisme COW (copie sur écriture) de php est impliqué, $b Une copie du $a original sera copiée et la relation de référence entre eux sera libérée, de sorte que le nombre de références (refcount) de a est réduit à 1.

Ensuite, le nombre de références à a devient 0 après avoir utilisét($a). Ceci sera considéré comme une variable inutile et libérera de l'espace.

Donnez un exemple

$a = [1];
$a[1] = &$a;
unset($a);
Copier après la connexion

Avant unset($a), le type de $a est un type de référence

a:
(refcount=2, is_ref=1),
array (size=2)
  0 => (refcount=1, is_ref=0),int 1
  1 => (refcount=2, is_ref=1),
    &array<
Copier après la connexion

Explication détaillée du mécanisme de récupération de place de PHP7

unset( $ a) Après ça, ça devient comme ça

Explication détaillée du mécanisme de récupération de place de PHP7

A ce moment, quand on désactive l'opération, le refcount passe de 2 à 1, car il y a une référence interne pointant à $a, donc là où il se trouve à l'extérieur, l'espace occupé ne sera pas détruit.

Ensuite, notre référence externe a été cassée et nous ne pouvons pas l'utiliser. Il devient un "orphelin", appelé pointeur sauvage en langage C. En php, cela s'appelle une référence circulaire. Fuite de mémoire. Si vous souhaitez détruire la variable, vous ne pouvez qu'attendre la fin du script php.

Fuites de mémoire causées par des références circulaires

Afin de nettoyer ces déchets, deux critères sont introduits

● Si le nombre de références est réduit à zéro, la variable dans laquelle il se trouve Le conteneur sera vidé (gratuit) et n'est pas une poubelle

● Si le nombre de références d'un zval est toujours supérieur à 0 après avoir été réduit, alors il entrera dans la poubelle faire du vélo. Deuxièmement, pendant un cycle de déchets, découvrez quelles parties sont des déchets en vérifiant si le nombre de références est réduit de 1 et en vérifiant quels conteneurs de variables ont zéro référence.

Les références circulaires n'apparaissent essentiellement que dans les tableaux et les objets. L'objet est parce qu'il est lui-même une référence

Le processus de recyclage de l'objet et du tableau

Le garbage collection de PHP7 se compose de deux parties, l'une est le garbage collector et l'autre est l'algorithme de garbage collection.

Le garbage collector collecte les éléments que nous venons de mentionner qui peuvent être des déchets dans le pool de recyclage, c'est-à-dire que les informations zend_refcount de la variable sont placées dans le pool de recyclage. Lorsque la valeur du pool de recyclage atteint un certain montant, il sera traité uniformément.

Le processus de traitement est relativement simple.

Parcourez chaque variable du pool de recyclage, puis parcourez chaque membre en fonction de chaque variable. Si les membres sont toujours imbriqués, continuez le parcours. Définissez ensuite le refcount simulé de tous les membres sur -1. Si le nombre de références de la variable externe est 0 à ce moment. Cela peut alors être clairement considéré comme une poubelle. S'il est supérieur à 0, alors le nombre de références est restauré et retiré du pool de récupération de place.

Le principe du garbage collection

Si votre variable n'est pas une poubelle, alors une fois les références de toutes ses variables membres réduites de une, la référence de la variable totale ne sera pas 0.

Exemple

C'est difficile à dire, alors donnons un exemple. Lorsque j'ai parcouru sf.gg pour la première fois, j'ai vu une question sur GC et j'y ai répondu. Concernant le mécanisme de collecte des ordures du GC

le sujet est le suivant

Explication détaillée du mécanisme de récupération de place de 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 
模拟减结束,那么此变量被当成垃圾回收。
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:segmentfault.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal