Introduction au mécanisme de garbage collection des principes sous-jacents de PHP (exemple de code)

不言
Libérer: 2023-04-05 13:58:02
avant
2566 Les gens l'ont consulté

Ce que cet article vous apporte est une introduction au mécanisme de collecte des ordures (exemples de code) des principes sous-jacents de PHP. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. .

Le mécanisme de récupération de place php est un contenu familier mais pas très familier pour PHPer. Alors, comment PHP recycle-t-il la mémoire inutile ?

La structure de stockage interne des variables PHP

Tout d'abord, vous devez comprendre les connaissances de base pour faciliter la compréhension des principes du garbage collection. Tout le monde sait que php est écrit en C, donc la structure de stockage interne des variables php sera également liée au langage C, c'est-à-dire la structure de zval :

struct _zval_struct {
    union {
        long lval;
        double dval;
        struct {
            char *val;
            int len;
        } str;
        HashTable *ht;
        zend_object_value obj;
        zend_ast *ast;
    } value;                    //变量value值
    zend_uint refcount__gc;   //引用计数内存中使用次数,为0删除该变量
    zend_uchar type;           //变量类型
    zend_uchar is_ref__gc;    //区分是否是引用变量
};
Copier après la connexion

On peut le voir dans le contenu de la structure ci-dessus que chaque variable PHP sera composée de quatre parties : type de variable, valeur, nombre de références et s'il s'agit d'une variable de référence

Remarque : la structure zval ci-dessus est la structure après la version PHP5.3, car il n'a pas été introduit avant PHP5.3. Le nouveau mécanisme de récupération de place est GC, donc il n'y a pas de _gc dans le nom et après la version php7, la structure zval a été réécrite en raison de problèmes de performances, et le

le principe du comptage de références n'est plus énoncé ici

Compréhension Après la structure de stockage interne des variables PHP, nous découvrirons les principes liés à l'affectation des variables PHP et au premier mécanisme de récupération de place

Conteneur de variables

Variables non-tableaux et objets

Chaque fois lors de l'attribution d'une constante à une variable, un conteneur de variable

sera généré. Exemple :

$a = '许铮的技术成长之路';
xdebug_debug_zval('a')
Copier après la connexion
Résultat :

a: (refcount=1, is_ref=0)='许铮的技术成长之路'
Copier après la connexion
Variables tableau et objet

Générera un conteneur de variables avec le nombre d'éléments + 1

Exemple :

$b = [
'name' => '许铮的技术成长之路',
'number' => 3
];
xdebug_debug_zval('b')
Copier après la connexion
Résultat :

b: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='许铮的技术成长之路', 'number' => (refcount=1, is_ref=0)=3)
Copier après la connexion
Principe d'affectation (technologie de copie sur écriture)

Après avoir compris l'affectation constante, réfléchissons à l'affectation entre variables du point de vue de la mémoire

Exemple :

$a = [
'name' => '许铮的技术成长之路',
'number' => 3
]; //创建一个变量容器,变量a指向给变量容器,a的ref_count为1
$b = $a; //变量b也指向变量a指向的变量容器,a和b的ref_count为2
xdebug_debug_zval('a', 'b');
$b['name'] = '许铮的技术成长之路1';//变量b的其中一个元素发生改变,此时会复制出一个新的变量容器,变量b重新指向新的变量容器,a和b的ref_count变成1
xdebug_debug_zval('a', 'b');
Copier après la connexion
Résultat :

a: (refcount=2, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='许铮的技术成长之路', 'number' => (refcount=1, is_ref=0)=3)
b: (refcount=2, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='许铮的技术成长之路', 'number' => (refcount=1, is_ref=0)=3)
a: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='许铮的技术成长之路', 'number' => (refcount=1, is_ref=0)=3)
b: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='许铮的技术成长之路1', 'number' => (refcount=1, is_ref=0)=3)
Copier après la connexion
Ainsi, lorsque la variable a est affectée à la variable b, un nouveau conteneur de variables n'est pas immédiatement généré, mais la variable b est pointée vers le conteneur de variables pointé par la variable a, c'est-à-dire que la mémoire est "partagée" ; et lorsqu'un élément de la variable b change Lorsque la copie du conteneur de variable se produit réellement, c'est

写时复制技术

Le décompte de références est remis à 0

Lorsque le ref_count du conteneur de variables est remis à 0, cela signifie que le conteneur de variables sera détruit. Implémentation du recyclage de la mémoire, qui est également

php5.3版本之前的垃圾回收机制

Exemple :

Résultat :
$a = "许铮的技术成长之路";
$b = $a;
xdebug_debug_zval('a');
unset($b);
xdebug_debug_zval('a');
Copier après la connexion

Problème de fuite de mémoire causé par une référence circulaire
a: (refcount=2, is_ref=0)='许铮的技术成长之路'
a: (refcount=1, is_ref=0)='许铮的技术成长之路'
Copier après la connexion

Cependant, il y a une faille dans le mécanisme de récupération de place avant PHP5.3, c'est-à-dire lorsqu'un enfant L'élément dans un tableau ou un objet fait référence à son élément parent, et si son élément parent est supprimé à ce moment, le conteneur de variable ne sera pas supprimé car ses éléments enfants pointent toujours vers le conteneur de variable, mais puisqu'il n'y a aucun symbole pointant. au conteneur de variables dans n'importe quelle portée, elles ne peuvent pas être effacées, donc une fuite de mémoire se produira jusqu'à la fin de l'exécution du script

Par exemple :

Depuis la sortie de cet exemple n'est pas facile, utilisez un schéma pour le représenter, comme le montre la figure :
$a = array( 'one' );
$a[] = &$a;
xdebug_debug_zval( 'a' );
Copier après la connexion


Introduction au mécanisme de garbage collection des principes sous-jacents de PHP (exemple de code)Exemple :

Comme le montre la photo :
unset($a);
xdebug_debug_zval('a');
Copier après la connexion


Introduction au mécanisme de garbage collection des principes sous-jacents de PHP (exemple de code)Nouveau mécanisme de récupération de place

Le mécanisme de mise en mémoire tampon racine a été introduit après la version php5.3, qui est le paramètre par défaut au démarrage de php Spécifiez le nombre de zvals dans le tampon racine (la valeur par défaut est 10 000). Lorsque PHP trouve un zval avec une référence circulaire, il le placera dans le tampon racine lorsque le nombre spécifié dans le fichier de configuration (la valeur par défaut). est 10000) Après cela, un garbage collection sera effectué pour résoudre le problème de fuite de mémoire causé par les références circulaires

Critères de confirmation comme garbage

1 Si le nombre de références est réduit à zéro, le conteneur de variables sera effacé (gratuit), pas poubelle

2. 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 le cycle poubelle. 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.


Résumé

Mécanisme de récupération de place :

1 Basé sur le mécanisme de comptage de références de PHP (seul ce mécanisme était disponible avant PHP5.3)

2. en même temps, lorsque PHP découvre qu'il existe un zval avec une référence circulaire, il le placera dans le tampon racine. Lorsque le tampon racine atteint le numéro spécifié dans le fichier de configuration, un garbage collection sera effectué pour résoudre la fuite de mémoire provoquée. par références circulaires Problème (php5.3 a commencé à introduire ce mécanisme)

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:
php
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
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!