¿Cómo funciona el nuevo mecanismo automático de recuento de referencias?


¿Puede alguien explicarme brevemente cómo funciona ARC? Sé que es diferente de la Recolección de Basura, pero me preguntaba exactamente cómo funcionaba.

Además, si ARC hace lo que hace GC sin obstaculizar el rendimiento, entonces ¿por qué Java utiliza GC? ¿Por qué no usa ARC también?

Author: Brad Larson, 2011-06-17

5 answers

Cada nuevo desarrollador que viene a Objective-C tiene que aprender las rígidas reglas de cuándo retener, liberar y autorelease objetos. Estas reglas incluso especifican convenciones de nomenclatura que implican el recuento de retención de objetos devueltos por métodos. La gestión de la memoria en Objective-C se convierte en una segunda naturaleza una vez que toma estas reglas en serio y las aplica consistentemente, pero incluso los desarrolladores de cacao más experimentados se equivocan de vez en cuando.

Con el analizador estático Clang, los desarrolladores de LLVM se dio cuenta de que estas reglas eran lo suficientemente confiables como para que pudieran construir una herramienta para señalar las fugas de memoria y las liberaciones excesivas dentro de las rutas que toma su código.

El siguiente paso lógico es el conteo automático de referencias (ARC). Si el compilador puede reconocer dónde debería estar reteniendo y liberando objetos, ¿por qué no hacer que inserte ese código por usted? Las tareas rígidas y repetitivas son lo que los compiladores y sus hermanos son grandes en. Los humanos olvidan cosas y cometen errores, pero las computadoras son mucho más consistentes.

Sin embargo, esto no lo libera completamente de preocuparse por la administración de memoria en estas plataformas. Describo el problema principal a tener en cuenta (retener ciclos) en mi respuesta aquí, que puede requerir un poco de reflexión de su parte para marcar punteros débiles. Sin embargo, eso es menor en comparación con lo que estás ganando en ARC.

En comparación con la gestión manual de memoria y la recolección de basura, ARC le ofrece lo mejor de ambos mundos al cortar la necesidad de escribir código retain / release, sin tener los perfiles de memoria de detención y diente de sierra vistos en un entorno de recolección de basura. Las únicas ventajas que tiene la recolección de basura sobre esto son su capacidad para lidiar con los ciclos de retención y el hecho de que las asignaciones de propiedades atómicas son baratas (como se discute aquí). Sé que estoy reemplazando todo mi código GC Mac existente con implementaciones ARC.

En cuanto a si esto podría extenderse a otros idiomas, parece orientado alrededor del sistema de conteo de referencias en Objective-C. Podría ser difícil aplicar esto a Java u otros lenguajes, pero no conozco lo suficiente sobre los detalles del compilador de bajo nivel para hacer una declaración definitiva allí. Dado que Apple es el que impulsa este esfuerzo en LLVM, Objective-C vendrá primero a menos que otra parte comprometa recursos significativos para ello.

La presentación de esta conmocionada desarrolladores en WWDC, por lo que la gente no era consciente de que algo como esto podría ser Terminado. Puede aparecer en otras plataformas con el tiempo, pero por ahora es exclusivo de LLVM y Objective-C.

 240
Author: Brad Larson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:35

ARC es solo reproducir el antiguo retain/release (MRC) con el compilador calculando cuándo llamar a retain/release. Tenderá a tener un mayor rendimiento, menor uso de memoria pico y un rendimiento más predecible que un sistema GC.

Por otro lado, algunos tipos de estructura de datos no son posibles con ARC (o MRC), mientras que GC puede manejarlos.

Como ejemplo, si tiene una clase llamada node, y node tiene un NSArray de hijos, y una sola referencia a su padre que " solo funciona" con GC. Con ARC (y el conteo manual de referencias también) tiene un problema. Cualquier nodo dado será referenciado desde sus hijos y también desde su padre.

Como:

A -> [B1, B2, B3]
B1 -> A, B2 -> A, B3 -> A

Todo está bien mientras se usa A (por ejemplo, a través de una variable local).

Cuando haya terminado con él (y B1/B2/B3), un sistema GC finalmente decidirá mirar todo lo que pueda encontrar a partir de la pila y los registros de la CPU. Nunca encontrará A, B1, B2, B3 por lo que los finalizará y reciclará memoria en otros objetos.

Cuando usa ARC o MRC, y termina con A, tiene un refcount de 3 (B1, B2 y B3 todos lo hacen referencia), y B1/B2/B3 todos tendrán un recuento de referencia de 1 (el NSArray de A contiene una referencia a cada uno). Así que todos esos objetos permanecen vivos aunque nada pueda usarlos.

La solución común es decidir que una de esas referencias debe ser débil (no contribuir al recuento de referencias). Eso funcionará para algunos patrones de uso, por ejemplo, si referencia B1/B2 / B3 solo a través de A. Sin embargo, en otros patrones falla. Por ejemplo, si a veces se aferra a B1, y espera subir de nuevo a través del puntero padre y encontrar A. Con una referencia débil si solo se aferra a B1, A puede (y normalmente lo hará) evaporarse, y tomar B2 y B3 con él.

A veces esto no es un problema, pero algunas formas muy útiles y naturales de trabajar con estructuras complejas de datos son muy difíciles de usar con ARC/MRC.

Así que ARC apunta al mismo tipo de problemas objetivos GC. Sin embargo, ARC funciona en un conjunto más limitado de patrones de uso que GC, por lo que si tomaras un lenguaje GC (como Java) e injertaras algo como ARC en él, algunos programas no funcionarían más (o al menos generarían toneladas de memoria abandonada, y podrían causar serios problemas de intercambio o quedarse sin memoria o espacio de intercambio).

También se puede decir que ARC pone una mayor prioridad en el rendimiento (o tal vez la previsibilidad), mientras que GC pone una mayor prioridad en ser un genérico solución. Como resultado, GC tiene menos demandas predecibles de CPU / memoria,y un rendimiento menor (normalmente) que ARC, pero puede manejar cualquier patrón de uso. ARC funcionará mucho mejor para muchos muchos patrones de uso comunes, pero para unos pocos (¡válido!) patrones de uso se caerá y morirá.

 21
Author: Stripes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-04 17:03:53

Magia

Pero más específicamente ARC funciona haciendo exactamente lo que haría con su código (con ciertas diferencias menores). ARC es una tecnología de tiempo de compilación, a diferencia de GC, que es tiempo de ejecución y tendrá un impacto negativo en su rendimiento. ARC rastreará las referencias a los objetos por usted y sintetizará los métodos retain/release/autorelease de acuerdo con las reglas normales. Debido a este ARCO también puede liberar cosas tan pronto como ya no son necesarias, en lugar de lanzarlas en una piscina de autorelease puramente por el bien de la convención.

Algunas otras mejoras incluyen poner a cero referencias débiles, copia automática de bloques en el montón, aceleraciones en todos los ámbitos (6x para grupos de autorelease!).

Una discusión más detallada sobre cómo funciona todo esto se encuentra en el LLVM Docs en ARC.

 4
Author: Joshua Weinberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-17 13:08:25

Varía mucho de la recolección de basura. ¿Ha visto las advertencias que le dicen que puede estar filtrando objetos en diferentes líneas? Esas declaraciones incluso le dicen en qué línea asignó el objeto. Esto se ha dado un paso más allá y ahora se puede insertar retain/release declaraciones en las ubicaciones adecuadas, mejor que la mayoría de los programadores, casi el 100% de las veces. De vez en cuando hay algunos casos extraños de objetos retenidos que usted necesita para ayudar a cabo con.

 3
Author: FreeAsInBeer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-17 12:49:52

Muy bien explicado por la documentación para desarrolladores de Apple. Lee "Cómo funciona ARC"

Para asegurarse de que las instancias no desaparezcan mientras sean necesarias, ARC rastrea cuántas propiedades, constantes y variables se refieren actualmente a cada instancia de clase. ARC no desasignará una instancia mientras siga existiendo al menos una referencia activa a esa instancia.

Para asegurarse de que las instancias no desaparecen mientras todavía son necesarias, las pistas de arco cuántas propiedades, constantes y variables se refieren actualmente a cada instancia de clase. ARC no desasignará una instancia mientras siga existiendo al menos una referencia activa a esa instancia.

Conocer las diferencias. entre la recolección de basura y ARC: Lea esto

 0
Author: Lalit Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:33