php recolección de basura relacionada

Después de leer varios artículos sobre la recolección de basura php y los cambios de php5.3 ~ php7, personalmente resumí algunos puntos. Se resume principalmente a partir de los cambios en la estructura de la variable y los cambios en el mecanismo de recolección de basura:

1. Variables

En
la etapa de php5.3 ~ php7 , la definición de variables se divide en

zval_struct {
    
    zval_value value;
    zend_uint ref_count_gc;
    zend_uchar is_ref_gc;
    zend_uchar type;
}
zvalue_value {
    long;
    double;
    struct {

    } str;
    Hashtable * ht;
    zend_obj_val obj;
}

Hashtable :
zend_array {
    zend_refcount_h gc;
    ....(那串复杂的结构,包括了 bucket *arData等)
}

php7 está integrado en una estructura de datos y el recuento de referencias es una estructura

typedef struct _zend_refcounted_h {
    uint32_t         refcount; // 记录 zend_value 的引用数
    union {
        struct {
            zend_uchar    type,  // zend_value的类型, 与zval.u1.type一致
            zend_uchar    flags, 
            uint16_t      gc_info // GC信息,记录在 gc 池中的位置和颜色,垃圾回收的过程会用到
        } v;
        uint32_t type_info;
    } u;
} zend_refcounted_h;

 

2. Mecanismo de recolección de basura
1. Basado en el mecanismo de conteo de referencias de PHP (el único mecanismo antes de PHP 5.3)
2. Al mismo tiempo, use el mecanismo de búfer raíz. Cuando PHP encuentre un zval de referencia circular, lo invertirá en búfer raíz, cuando el búfer raíz alcance el número especificado en el archivo de configuración, se recolectará basura para resolver la pérdida de memoria causada por referencias circulares (php5.3 comenzó a introducir este mecanismo)
3. php7 usa tres marcas

otras instrucciones:

1. La posición de refcount en php7 también se ha movido de la estructura zval a zval_value, por lo que no todos los tipos de datos tendrán operaciones de conteo de referencias, como integer, punto flotante, booleano, NULL, estos tipos de datos simples no tienen refcount
2. El algoritmo utilizado por la recolección de basura php5.3 ~ 7:
Solo el zval referenciado circularmente se colocará en el búfer (la condición específica es: si el recuento de la variable se reduce y es mayor que 0, PHP no lo hará inmediatamente Esta variable es basura identificado y reciclado, pero colocado en un búfer ), y un recuento de referencia de 1 en el búfer significa que no hay ningún símbolo en el alcance actual que apunte al zval, es decir, basura que deba reciclarse.
Por lo tanto, siempre que el búfer raíz esté lleno, php atravesará todos los contenedores de variables en el búfer raíz para la eliminación simulada y realizará una recuperación simulada después de la eliminación simulada. Pero php solo restaurará refcount> 0 después de la eliminación simulada, entonces no hay forma de restaurar refcount = 0, que es basura ~

3. La recolección de basura de php7 usa marcas de tres colores:

Descripción del proceso:

Una variable solo se puede agregar al búfer una vez. Para evitar la adición repetida, zend_refcounted_h.gc_info se establecerá en GC_PURPLE después de agregar la variable, es decir, se marcará como púrpura y no se insertará repetidamente en el futuro.

El búfer de basura es una lista doblemente enlazada. Una vez que el búfer está lleno, se inicia el proceso de verificación de basura: atraviesa el búfer, atraviesa todos los miembros de la variable actual y luego disminuye el recuento de ref. Del miembro en 1 (si el miembro también contiene submiembros, también se realiza Recorrido recursivo, es decir, recorrido en profundidad primero), y finalmente verifica la referencia de la variable actual, si se reduce a 0, es basura. El principio central de este algoritmo es: la basura es causada por miembros que hacen referencia a sí mismos, entonces todos los miembros se reducen. Si se encuentra que el recuento de ref. De la variable en sí se convierte en 0, significa que todas las referencias son de sus propios miembros, es decir, en cualquier otro lugar, ya no lo use, entonces es basura y necesita ser reciclado. Por el contrario, no es basura y debe eliminarse del búfer. El proceso específico es el siguiente:

(1) Inicie el recorrido desde las raíces de la lista vinculada al búfer, marque el valor actual en gris (zend_refcounted_h.gc_info se establece en GC_GREY) y luego realice un recorrido en profundidad en los miembros del valor actual, reduzca el recuento de ref. el valor del miembro en 1, y también marcarlo como gris;

(2) Recorra repetidamente la lista vinculada al búfer, verifique si la referencia del valor actual es 0, si es 0, de hecho es basura, y márquelo como blanco (GC_WHITE), si no es 0, excluye la posibilidad de que todos las referencias provienen de sus propios miembros, lo que significa que también hay referencias externas, que no son basura. En este momento, debido a que el paso (1) ha realizado la operación refcount menos 1 en el miembro, debe restaurarse nuevamente, y todos los miembros se atraviesan en profundidad, y el recuento de miembros se incrementa en 1 y se marca como negro al mismo tiempo;

(3) Vuelva a recorrer la lista de enlaces de búfer, elimine los nodos que no son GC_WHITE de la lista de enlaces de raíces y, finalmente, toda la basura real en la lista de enlaces de raíces, y finalmente elimine estos desechos.

De: https://learnku.com/articles/33451

Supongo que te gusta

Origin blog.csdn.net/jayxujia123/article/details/115049850
Recomendado
Clasificación