Maison  >  Article  >  développement back-end  >  Explication détaillée du mécanisme GC en PHP

Explication détaillée du mécanisme GC en PHP

*文
*文original
2017-12-27 14:12:384310parcourir

Cet article présente principalement l'interprétation du mécanisme de garbage collection en PHP. Qu'il ait la fonction GC est une préoccupation importante dans le développement d'un langage de programmation. J'espère que cela aide tout le monde.

Concept GC de base de PHP
Le langage PHP, comme d'autres langages, dispose d'un mécanisme de récupération de place. Donc, ce que nous voulons vous expliquer aujourd'hui est lié au mécanisme de garbage collection PHP. J'espère que cela aide tout le monde. Expérience de l'application PHP strtotime PHP memory_get_usage() gère la mémoire Explication détaillée des problèmes d'utilisation des variables globales PHP non définies La fonction PHP unset() détruit les variables pour vous apprendre à implémenter rapidement la vérification complète des autorisations du site PHP 1. Mécanisme de récupération de place PHP (Garbage Collector, appelé comme GC) en PHP, lorsqu'aucune variable ne pointe vers cet objet, cet objet devient un déchet. PHP le détruira en mémoire ; il s'agit du mécanisme d'élimination des déchets GC de PHP pour empêcher le débordement de mémoire. Lorsqu'un thread PHP se termine, tout l'espace mémoire actuellement occupé sera détruit et tous les objets du programme en cours seront détruits en même temps. Le processus GC commence généralement à s'exécuter à chaque SESSION. Le but de gc est de détruire et de supprimer automatiquement les fichiers de session après leur expiration. 2. __destruct /unset __destruct() Le destructeur est exécuté lorsque l'objet poubelle est recyclé.
unset détruit la variable pointant vers l'objet, pas l'objet. 3. Mécanisme de collecte de mémoire de session et PHP En raison du mécanisme de fonctionnement de PHP, il ne dispose pas de thread démon pour analyser régulièrement les informations de session et déterminer si elles sont invalides. Lorsqu'une requête valide se produit, PHP utilisera les variables globales session.gc_probability. et session La valeur de .gc_pisor détermine s'il faut activer un GC. Par défaut, session.gc_probability=1, session.gc_pisor =100 signifie qu'il y a 1% de possibilité de démarrer un GC (c'est-à-dire qu'il n'y a qu'un gc sur 100). requêtes) Sera démarré avec l'une des 100 requêtes). Le travail du mécanisme de récupération de place PHP consiste à analyser toutes les informations de session, à soustraire l'heure de la dernière modification de la session de l'heure actuelle et à la comparer avec le paramètre session.gc_maxlifetime. . Si le temps de survie dépasse gc_maxlifetime (24 minutes par défaut), la session sera supprimée.
Cependant, si votre serveur Web possède plusieurs sites, GC peut avoir des résultats inattendus lors du traitement de sessions sur plusieurs sites. La raison en est que lorsque GC fonctionne, il ne fera pas de distinction entre les sessions de différents sites. le résoudre ?
1. Modifiez session.save_path, ou utilisez session_save_path() pour enregistrer la session de chaque site dans un répertoire dédié
2. Fournissez le taux de démarrage de GC Naturellement, le taux de démarrage du mécanisme de récupération de place PHP est. amélioré, et le système Les performances seront également réduites en conséquence, ce qui n'est pas recommandé.
3. Déterminez la durée de survie de la session en cours dans le code et utilisez session_destroy() pour la supprimer.


Connaissance de base du comptage de références
Chaque variable PHP existe dans un conteneur de variables appelé "zval". Un conteneur de variables zval, en plus de contenir le type et la valeur de. la variable, Il comprend également deux octets d'informations supplémentaires. Le premier est "is_ref", qui est une valeur booléenne utilisée pour identifier si cette variable appartient à un ensemble de références. Grâce à cet octet, le moteur PHP peut combiner des variables ordinaires et des références. Les variables sont distinguées. Puisque PHP permet aux utilisateurs d'utiliser des références personnalisées en utilisant &, il existe également un mécanisme de comptage de références interne dans le conteneur de variables zval pour optimiser l'utilisation de la mémoire. pointeur vers ceci Le nombre de variables (également appelées symboles) dans le conteneur de variables zval

Lorsqu'une variable se voit attribuer une valeur constante, un conteneur de variables zval sera généré, comme indiqué dans l'exemple suivant :


  <?php 
      $a = "new string"; 
  ?>



Dans l'exemple ci-dessus, la nouvelle variable est a, qui est générée dans la portée actuelle et les types. de chaîne et un conteneur de variable avec la valeur "nouvelle chaîne". Dans les deux octets d'informations supplémentaires, "is_ref" est défini sur false par défaut car aucune référence personnalisée n'est générée. "refcount" est défini sur 1 car il n'y a que A. La variable utilise ce conteneur de variables. Appelez xdebug pour afficher le contenu de la variable :


  <?php 
      $a = "new string";
      xdebug_debug_zval(&#39;a&#39;); 
  ?>



Le code ci-dessus affichera :


  a: (refcount=1, is_ref=0)=&#39;new string&#39;



Ajouter un nombre de références à la variable a


  <?php 
      $a = "new string"; 
      $b = $a; 
      xdebug_debug_zval(&#39;a&#39;); 
  ?>



Le code ci-dessus affichera :


  a: (refcount=2, is_ref=0)=&#39;new string&#39;



À l'heure actuelle, le nombre de références est de 2, car le même conteneur de variables est associé à la variable a et à la variable b. PHP ne copiera pas le conteneur de variables généré lorsque cela n'est pas nécessaire. Le conteneur de variables sera détruit lorsque ". refcount" devient 0. Lorsqu'une variable associée à une certaine variable quitte sa portée (par exemple : l'exécution de la fonction se termine), ou que la fonction unset() est appelée sur la variable, le "refcount" sera réduit de 1, car le L'exemple suivant illustre :


<?php 
  $a = "new string"; 
  $b = $c = $a; 
  xdebug_debug_zval(&#39;a&#39;); 
  unset($b, $c); 
  xdebug_debug_zval(&#39;a&#39;); 
?>



Le code ci-dessus affichera :


  a: (refcount=3, is_ref=0)=&#39;new string&#39; a: (refcount=1, is_ref=0)=&#39;new string&#39;

Si nous exécutons maintenant unset($a), le conteneur contenant le type et la valeur $ sera supprimé de la mémoire

Types composés (types composés)

Quand les choses deviennent un peu plus compliquées lorsque l'on considère des types composites comme un tableau et un objet. Contrairement aux valeurs de type scalaire, les variables de type tableau et objet stockent leurs membres ou propriétés dans leur propre table de symboles. L'exemple générera trois conteneurs de variables zval


<?php 
  $a = array(&#39;meaning&#39; => &#39;life&#39;, &#39;number&#39; => 42);
  xdebug_debug_zval(&#39;a&#39;); 
?>

以上代码输出:


  a: (refcount=1, is_ref=0)=array (&#39;meaning&#39; => (refcount=1, is_ref=0)=&#39;life&#39;, &#39;number&#39; => (refcount=1, is_ref=0)=42)

这三个zval变量容器是:a,meaning,number.增加和减少refcount的规则和上面提到的一样


特例,添加数组本身作为数组元素时:


<?php 
  $a = array(&#39;one&#39;); 
  $a[] = &$a; 
  xdebug_debug_zval(&#39;a&#39;); 
?>

以上代码输出的结果:


  a: (refcount=2, is_ref=1)=array (0 => (refcount=1, is_ref=0)=&#39;one&#39;, 1 => (refcount=2, is_ref=1)=...)

可以看到数组a和数组本身元素a[1]指向的变量容器refcount为2

当对数组$a调用unset函数时,$a的refcount变为1,发生了内存泄漏

清理变量容器的问题
尽管不再有某个作用域中的任何符号指向这个结构(就是变量容器),由于数组元素"1"仍然指向数组本身,所以这个容器不能被消除.因为没有另外的符号指向它,用户没有办法清除这个结构,结果就会导致内存泄漏.庆幸的是,php将在请求结束时清除这个数据结构,但是php清除前,将耗费不少内存空间


回收周期
5.3.0PHP使用了新的同步周期回收算法,来处理上面所说的内存泄漏问题

首先,我们先要建立一些基本规则:
如果一个引用计数增加,它将继续被使用,当然就不再垃圾中.如果引用技术减少到零,所在的变量容器将被清除(free).就是说,仅仅在引用计数减少到非零值时,才会产生垃圾周期(grabage cycle).其次,在一个垃圾周期中,通过检查引用计数是否减1,并且检查哪些变量容器的引用次数是零,来发现哪部分是垃圾

2015810114143348.png (429×552)

为避免不得不检查所有引用计数可能减少的垃圾周期,这个算法把所有可能根(possible roots 都是zval变量容器),放在根缓冲区(root buffer)中(用紫色标记),这样可以同时确保每个可能的垃圾根(possible garbage root)在缓冲区只出现一次.仅仅在根缓冲区满了时,才对缓冲区内部所有不同的变量容器执行垃圾回收操作。

相关推荐:

php底层分析的视频和课件分享

浅析PHP底层的运行机制和工作原理

PHP底层工作原理_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