Comprender la liberación automática en Objective-C
Este artículo es el anterior: Comprender la extensión y el complemento de ARC en Objective-C
El sistema operativo implementa una fábrica de subprocesos llamada grupo de subprocesos y un administrador cooperante es llamado centro de despacho. El sistema iOS no tiene una interfaz para operar directamente el grupo de subprocesos. La creación, programación y destrucción de subprocesos se deja completamente en manos del grupo de subprocesos. Cuando intentamos crear un subproceso, el centro de despacho lo verificará. el estado de ejecución del grupo de subprocesos, el número de subprocesos en ejecución y la estrategia de ejecución determinan el siguiente proceso de ejecución, ya sea solicitar la ejecución del subproceso directamente o colocarlo en la cola del búfer. Cuando se ejecuta, el grupo de subprocesos decide si. para crear un nuevo hilo o reutilizar el hilo inactivo existente. Los hilos que están inactivos se reciclarán (generalmente alrededor de 10)
El sistema operativo iOS está equipado con un conjunto de estructuras de datos para la ejecución de subprocesos, una pila, un autoreleasePool, un runloop (carga diferida) y algunos para controlar la variable de bandera de estado
Bien ~ volvamos al problema en sí
Hablemos primero de la conclusión:
Veamos la demostración nuevamente, aquí solo analizamos el hilo no principal:
Creé una cola en serie como arriba, escribí un bucle infinito y seguí creando cadenas en el área del montón. pero la memoria no aumentará ni un poquito. El motivo se mencionó en el artículo anterior Comprensión de ARC en Objective-C. Este objeto se liberará directamente y no se agregará al autoreleasePool
Modificar:
Descubrirá que la creación de un objeto de liberación automática mediante un hilo no principal hará que la memoria aumente sin cesar hasta OOM
p>Modificar nuevamente:
El resultado La razón es que la memoria no aumentará en absoluto. Los datos solo corresponden a la conclusión anterior. Para aquellos que quieran saber el motivo, pueden leer el artículo del senior a continuación. Un breve análisis basado en el código fuente más reciente (puede que no sea el código fuente más reciente, la versión objc4-781.2 cuando el autor comenzó a leer el código fuente. Por cierto, le diré cómo verificar el código fuente). Enlace del código fuente
Encontrará que AutoreleasePoolPage es una clase C ++ que hereda AutoreleasePoolPageData La implementación específica es muy larga y algunas implementaciones de funciones se omiten aquí
Todavía es muy larga. pero es importante comprender el principio. Eche un vistazo a los comentarios de Apple
/***************************. *************** *******************************
Implementación del grupo de liberación automática
El grupo de liberación automática de un subproceso es una pila de punteros.
Cada puntero es un objeto a liberar o POOL_BOUNDARY, que es
un límite de grupo de liberación automática.
Un token de grupo es un puntero al POOL_BOUNDARY para ese grupo. Cuando
se abre el grupo, se libera cada objeto más caliente que el centinela.
La pila se divide en una lista de páginas con doble enlace. Las páginas se agregan
y se eliminan.
editado nuevamente según sea necesario.
El almacenamiento local de subprocesos apunta a la página activa, donde se almacenan los objetos liberados automáticamente
.
******** ************************************************** * *************/
/****************************** ******** *******************************************
Implementación del grupo de liberación automática
El grupo de liberación automática del subproceso es una serie de punteros declarados en la pila.
Cada puntero es un objeto que debe liberarse o un POOL_BOUNDARY, que es el
límite del grupo de liberación automática.
El token es un puntero al POOL_BOUNDARY del grupo. Cuando
se expulsa la piscina, se libera todo objeto más caliente que el centinela.
La pila se divide en una lista doblemente enlazada de AutoreleasePoolPage. Las páginas se agregan
y se eliminan según sea necesario.
Encadene los puntos de almacenamiento local a la página del punto de acceso donde se encuentran los datos más recientes almacenados en el grupo de liberación automática.
******************************************* ***************************/
Después de leer esta nota, ¿creo que no es necesario continuar? , Una palabra, clara y completa
El siguiente puntero sirve como cursor y apunta a la siguiente posición del objeto de liberación automática que se agregó recientemente en la parte superior de la pila cuando se agrega un nuevo objeto a la. autoreleasePool, se obtiene la dirección del siguiente puntero y se almacena el siguiente puntero. Mueva 8 bytes hacia la parte superior de la pila
Cada autoreleasePool se vinculará al hilo actual cuando se inicialice. la función de inicialización de AutoreleasePoolPage
El primer parámetro es el identificador de AutoreleasePoolPage. El segundo parámetro es un puntero de función. Esta función se ejecutará antes de que salga el hilo, que es tls_dealloc.
Antes de que el hilo entre en suspensión, runloop llamará a objc_autoreleasePoolPop. Excepto por el primer paso, el proceso anterior es el mismo.
¿Está bien unidireccional? Sí, pero la velocidad de consulta disminuirá a un nivel exponencial. ¿Qué debo hacer si quiero eliminar la penúltima página después de eliminar la página en la parte superior de la pila? Recorrerla desde el principio, n-1 veces, y luego n. -2 veces... ...
Entonces, ¿por qué está diseñado como una lista enlazada de dos vías? Es muy eficiente, eso es todo.