Maison  >  Article  >  développement back-end  >  Comprendre les principes du garbage collection PHP en dix minutes

Comprendre les principes du garbage collection PHP en dix minutes

王林
王林original
2019-09-04 09:52:484327parcourir

Comprendre les principes du garbage collection PHP en dix minutes

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 ?

Structure de stockage en mémoire 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;
    } value;                    //变量value值
    zend_uint refcount__gc;   //引用计数内存中使用次数,为0删除该变量
    zend_uchar type;           //变量类型
    zend_uchar is_ref__gc;    //区分是否是引用变量
};

D'après le contenu de la structure ci-dessus, nous Vous pouvez voir que chaque variable php est 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 php5.3. 3, aucun nouveau n'a été introduit. Le mécanisme de récupération de place est GC, il n'y a donc 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, elle ne sera donc pas décrite ici.

Principe du comptage de références :

Après avoir compris la structure de stockage interne des variables php, nous découvrirons les principes liés à l'affectation des variables php et au mécanisme de récupération de place précoce

Conteneur de variable

Variables non-tableaux et objets

Chaque fois qu'une constante est affectée à une variable, un conteneur de variable est généré.

Exemple :

$a = '许铮的技术成长之路';
xdebug_debug_zval('a')

Résultat :

a: (refcount=1, is_ref=0)='许铮的技术成长之路'

variables de tableau et d'objet

produiront des numéros d'éléments Conteneur variable de nombre + 1

Exemple :

$b = [
'name' => '许铮的技术成长之路',
'number' => 3
];
xdebug_debug_zval('b')

Résultat :

b: (refcount=1, is_ref=0)=array ('name' => (refcount=1, is_ref=0)='许铮的技术成长之路', 
'number' => (refcount=1, is_ref=0)=3)

Principe d'affectation (copie-sur- technologie d'écriture)

Après avoir compris l'affectation constante, nous réfléchissons ensuite à l'affectation entre les 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');

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)

Donc , Lorsque la variable a est affectée à la variable b, un nouveau conteneur de variable n'est pas immédiatement généré, mais la variable b est pointée vers le conteneur de variable pointé par la variable a, c'est-à-dire que la mémoire est « partagée » et lorsqu'un élément de la variable b ; changements, la copie du conteneur de variables se produira réellement. Il s'agit de la technologie copie sur écriture

efface le nombre de références à 0

quand le conteneur de variables Lorsque le nombre ref_count est remis à 0, cela signifie que le conteneur de variables sera détruit et que le recyclage de la mémoire sera réalisé. Il s'agit également du mécanisme de récupération de place avant la version php5.3

Exemple : <.>

$a = "许铮的技术成长之路";
$b = $a;
xdebug_debug_zval(&#39;a&#39;);
unset($b);
xdebug_debug_zval(&#39;a&#39;);

Résultat :

a: (refcount=2, is_ref=0)='许铮的技术成长之路'
a: (refcount=1, is_ref=0)=&#39;许铮的技术成长之路&#39;

Fuite de mémoire causée par une référence circulaire :


Mais il y a une faille dans le mécanisme de récupération de place avant php5.3, c'est-à-dire lorsque l'élément enfant à l'intérieur du tableau ou de l'objet fait référence à son élément parent. Si l'élément parent est supprimé à ce moment-là, le conteneur de variables ne sera pas supprimé car ses éléments enfants pointent toujours. au conteneur de variables. Cependant, comme toutes les portées ont Il n'y a aucun symbole pointant vers le conteneur de variables, il ne peut donc pas être effacé, donc une fuite de mémoire se produira jusqu'à la fin de l'exécution du script

Exemple :

$a = array( &#39;one&#39; );
$a[] = &$a;
xdebug_debug_zval( &#39;a&#39; );

Étant donné que le résultat de cet exemple n'est pas bon, utilisez un diagramme pour le représenter, comme indiqué dans la figure :

Comprendre les principes du garbage collection PHP en dix minutesPar exemple :

unset($a);
xdebug_debug_zval(&#39;a&#39;);

Comme le montre la figure :


Comprendre les principes du garbage collection PHP en dix minutesNouveau mécanisme de récupération de place :

Le mécanisme de tampon racine a été introduit après la version php5 .3, c'est-à-dire que lorsque php démarre, il utilise par défaut un tampon racine avec un nombre spécifié de zvals (la valeur par défaut est 10 000). Lorsque php découvre qu'il existe une référence circulaire zval, elle sera placée dans le tampon racine. le tampon racine atteint le nombre spécifié dans le fichier de configuration (la valeur par défaut est 10000), un garbage collection sera effectué pour résoudre le problème de fuite de mémoire causé par des références circulaires

Critères de confirmation comme poubelle

:1. Si le nombre de références est réduit à zéro, le conteneur de variables sera effacé (libre) et n'est pas considéré comme un déchet

2 Si le nombre de références de A zval est toujours supérieur à 0 après avoir été réduit. , alors il entrera dans un cycle de déchets. 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. , et utilisez le mécanisme du tampon racine 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 nombre spécifié dans le fichier de configuration. être effectué. Résolvez le problème de fuite de mémoire causé par les références circulaires (php5.3 a commencé à introduire ce mécanisme)

Pour plus de problèmes connexes, veuillez visiter le site Web PHP chinois :

Tutoriel vidéo php

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!

Déclaration:
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