2012-01-06 13 views
109

Todavía tengo que usar ARC, ya que la mayoría del código en el proyecto en el que estoy trabajando en este momento fue escrito antes de iOS 5.0.¿ARC o no a ARC? ¿Cuáles son los pros y los contras?

Me preguntaba: ¿la conveniencia de no retener/liberar manualmente (y presumiblemente un código más confiable como resultado?) Supera cualquier "costo" de usar ARC? ¿Cuáles son sus experiencias con ARC y lo recomendaría?

Así:

  • ¿Cuánto beneficio puede ARC aportar a un proyecto?
  • ¿ARC tiene un costo como la recolección de basura en Java?
  • ¿Has estado usando ARC? Si es así, ¿cómo lo has encontrado hasta ahora?
+0

No hay recolección de basura en ipad/ios. ¿Estás hablando de OS X? – dasblinkenlight

+1

Mis disculpas, estoy usando términos de Java fuera de lugar. Me refiero a que con ARC, los objetos pueden mantenerse en la memoria por más tiempo de lo necesario, y luego liberarse como grupo en un grupo de auto-lanzamiento algún tiempo después. Es este efecto de que se mantengan y liberen con otros objetos más adelante, de manera similar a la recolección de basura de Java a la que me refiero. –

+3

@TenementFunster, para el mismo código (menos las llamadas para liberar), ARC mantendrá el objeto no más de largo que el código no ARC. De hecho, a menudo lo lanzará antes de lo que lo haría. Hay un pequeño número de cosas que son algo más lentas, pero aceleraron tanto los patrones comunes que empequeñecen el impacto en el rendimiento. Para muchos patrones comunes (que retienen un objeto que se devolvió con una liberación automática, por ejemplo), literalmente no se puede escribir a mano tan rápido como ARC lo hará automáticamente. –

Respuesta

145

No hay inconveniente. Úselo. Hazlo hoy. Es más rápido que tu código anterior. Es más seguro que tu código anterior. Es más fácil que tu código anterior. No es recolección de basura. No tiene overhead de tiempo de ejecución de GC. El compilador inserta retenciones y lanzamientos en todos los lugares que debería tener de todos modos. Pero es más inteligente que usted y puede optimizar los que no son realmente necesarios (al igual que puede desenrollar bucles, eliminar variables temporales, funciones en línea, etc.)

Bien, ahora le contaré sobre las pequeñas desventajas :

  • Si usted es un largo tiempo de ObjC desarrollador, se le contracción durante aproximadamente una semana cuando se ve el código de ARC. Lo superarás rápidamente.

  • Existen algunas (muy) pequeñas complicaciones en el código de Core Foundation. Hay un poco más de complicaciones al tratar cualquier cosa que trate un id como un void*. Cosas como C-arrays de id pueden tomar un poco más de pensar en hacer correctamente. El manejo elegante de ObjC va_args también puede causar problemas. La mayoría de las cosas que involucran matemáticas en un puntero ObjC son más complicadas. No deberías tener mucho de esto en ningún caso.

  • No puede poner id en struct. Esto es bastante raro, pero a veces se usa para empacar datos.

  • Si no siguió los nombres correctos de KVC y mezcló códigos ARC y no ARC, tendrá problemas de memoria. ARC utiliza la denominación de KVC para tomar decisiones sobre la gestión de la memoria. Si es todo el código ARC, entonces no importa porque lo hará de la misma manera "incorrecta" en ambos lados. Pero si está mezclado ARC/no ARC, entonces hay un desajuste.

  • ARC perderá memoria durante los lanzamientos de excepciones ObjC. Una excepción ObjC debe ser muy cercana a la finalización de su programa. Si está atrapando una cantidad significativa de excepciones ObjC, las está usando incorrectamente. Esto se puede reparar usando -fobjc-arc-exceptions, pero incurre en las penalizaciones que se describen a continuación:

  • ARC no perderá memoria durante la excepción ObjC o C++ arroja el código ObjC++, pero esto tiene un costo de tiempo y rendimiento espacial. Este es otro más en una larga lista de razones para minimizar el uso de ObjC++.

  • ARC no funcionará en absoluto en iPhoneOS 3 o Mac OS X 10.5 o versiones anteriores. (Esto me impide usar ARC en muchos proyectos.)

  • __weak los punteros no funcionan correctamente en iOS 4 o Mac OS X 10.6, lo cual es una lástima, pero bastante fácil de evitar. Los punteros __weak son geniales, pero no son el punto de venta # 1 de ARC.

Para el 95% + de código por ahí, ARC es brillante y no hay razón alguna para evitarlo (siempre que puede manejar las restricciones de la versión del sistema operativo). Para código que no sea ARC, puede pasar -fno-objc-arc archivo por archivo. Desafortunadamente, Xcode hace que esto sea mucho más difícil de lo que debería ser en la práctica. Probablemente deberías mover código que no sea ARC a un xcodeproj separado para simplificar esto.

En conclusión, cambie a ARC tan pronto como pueda y nunca mire hacia atrás.


EDITAR

que he visto un par de comentarios a lo largo de las líneas de "usando arco es ningún substituto para conocer las reglas de gestión de memoria de cacao." Esto es mayormente cierto, pero es importante entender por qué y por qué no. Primero, si todo su código usa ARC y usted viola el Three Magic Words en todas partes, no tendrá problemas. Escandaloso decirlo, pero ahí lo tienes. ARC podría retener algunas cosas que no quisiste retener, pero las liberará también, por lo que nunca importará. Si estuviera enseñando una nueva clase en Cocoa hoy, probablemente no dedicaría más de cinco minutos a las reglas de administración de memoria, y probablemente solo mencionaría las reglas de nombres de administración de memoria mientras hablaba de nombres de KVC. Con ARC, creo que en realidad podría convertirse en un programador principiante decente sin aprender las reglas de administración de memoria en absoluto.

Pero no podría convertirse en un programador intermedio decente. Necesita conocer las reglas para establecer un puente correcto con Core Foundation, y cada programador intermedio debe tratar con CF en algún momento. Y necesita conocer las reglas para el código mixto ARC/MRC. Y necesita conocer las reglas cuando comienza a jugar con los void* punteros al id (que sigue necesitando realizar KVO correctamente). Y bloques ... bueno, bloquear la administración de memoria es simplemente extraño.

Así que mi punto es que la administración de la memoria subyacente sigue siendo importante, pero cuando solía pasar un tiempo significativo estableciendo y replanteando las reglas para los nuevos programadores, con ARC se está convirtiendo en un tema más avanzado. Prefiero que los nuevos desarrolladores piensen en términos de gráficos de objetos en lugar de llenar sus cabezas con las llamadas subyacentes al objc_retain().

+0

Gracias por tomarse el tiempo para escribir todo eso Rob: después de leer todo lo que la gente ha escrito aquí, creo que el mayor obstáculo será mi desconfianza inicial de dejar que el compilador se preocupe y posiblemente dolor de manos después de abofetearme cada vez que empiezo a escribir - (tab) o rel- (tab)! –

+3

Una cosa de la que hay que tener mucho cuidado (también en el caso de los ARC, pero más en ARC porque ahora es tan invisible) es retener los ciclos. Mi consejo aquí es 1) si te encuentras almacenando un bloque objc como una variable de instancia, échale una mirada larga y dura para ver si puede capturar el objeto que es un ivar, incluso indirectamente. 2) De hecho, diseña tu gráfico de objetos, en lugar de simplemente dejar que suceda. Usted * debe * saber qué posee qué si quiere escribir un buen código. 3) Utilice diapositivas: http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory -crecimiento/ –

+1

@Catfish_Man Todos son buenos puntos. Retener bucles siempre ha sido un problema. El nuevo consejo de Apple es exactamente como dices en el n. ° 2. Necesitamos pensar sobre los gráficos de objetos en lugar de retenerlos y soltarlos. El # 1 es un problema serio con los bloques, y una de las varias razones por las cuales los bloques son una bendición mixta que debe abordarse con precaución. –

20

mejor, respuestas más técnicas que la mía vendrán, pero aquí va:

  • ARC = recolección de basura. No hay penalización de tiempo de ejecución, se realiza en tiempo de compilación.
  • ARC también! = Simplemente liberando automáticamente todo, como sugiere en su comentario. Lea la docs
  • Es impresionante una vez que se da cuenta de lo mucho que la gestión manual de referencia que fueron haciendo
  • Úsalo!
  • Una desventaja: mantener el código anterior, que no es de arco, de repente se vuelve muy tedioso.
+0

Sí, es por eso que no lo he usado hasta ahora, no estoy seguro de poder soportar la cantidad sustancial de pre código existente para convertirlo ... Definitivamente voy a probarlo el próximo proyecto. Gracias por su respuesta :) –

+0

No es que mantener el código anterior se vuelva más difícil, es que su expectativa ha cambiado. Por lo tanto, no es justo culpar a ARC por facilitar la vida. Xcode hace que sea fácil convertir su código anterior en ARC cuando esté listo, pero obviamente no puede usarlo si todavía necesita admitir versiones anteriores de iOS. – Caleb

+1

@Caleb No estaba culpando a ARC, es solo que es el único inconveniente que he visto hasta ahora: me ha echado a perder en el espacio de un solo proyecto. – jrturton

2

Lo he usado en un par de proyectos (ciertamente pequeños), y solo tengo buenas experiencias, tanto de rendimiento como de confiabilidad.

Una pequeña nota de precaución es que debe aprender lo que se debe hacer y lo que no: s de las referencias débiles para no causar ningún bucle de referencia si usted mismo está codificando su UI, el diseñador tiende a hacer buen trabajo de forma automática si configura su GUI usándolo.

16

¿Cuánto beneficio puede aportar ARC a un proyecto?

El beneficio es un grado significativo de protección contra errores comunes de administración de memoria. Las fugas causadas por la falla en la liberación de un objeto y los bloqueos debido a la falla en retener o liberar prematuramente un objeto deberían reducirse significativamente. Aún necesita comprender el modelo de memoria contada de referencia para que pueda clasificar sus referencias como fuertes o débiles, evitar retener ciclos, y así sucesivamente.

¿Cuánto cuesta realmente la recolección de basura?

No hay recolección de basura en iOS. ARC es similar a GC en que no tiene que retener o liberar objetos manualmente. A diferencia de GC, no existe un recolector de basura. El modelo de retención/liberación todavía se aplica, es solo que el compilador inserta las llamadas de administración de memoria apropiadas en su código en tiempo de compilación.

¿Has estado usando ARC? Si es así, ¿cómo lo has encontrado hasta ahora?

Es un poco desconcertante si está acostumbrado a hacer referencia al recuento, pero solo es cuestión de acostumbrarse y aprender a confiar en que el compilador realmente hará lo correcto. Se siente como una continuación del cambio en las propiedades que vino con Objective-C 2.0, que fue otro gran paso hacia la simplificación de la administración de la memoria. Sin las llamadas de administración de memoria manual, su código se vuelve un poco más corto y más fácil de leer.

El único problema con ARC es que no es compatible con las versiones anteriores de iOS, por lo que debe tenerlo en cuenta antes de decidirse a adoptarlo.

+1

¡Ahí está la mejor respuesta de la que estaba hablando! – jrturton

+1

Sí, excelente respuesta. Entonces, ¿realmente no hay ningún inconveniente para ARC aparte de tener que aprender a confiar en que funciona? Parece demasiado bueno para ser cierto en ese caso? –

4

Creo que ARC es una gran idea. Comparado con GC, puedes tener tu pastel y comértelo también. Tiendo a creer que MRC impone una "disciplina" invalorable hacia la gestión de la memoria que todos se beneficiarían de tener. Pero también estoy de acuerdo en que el problema real a tener en cuenta es la propiedad de objetos y los gráficos de objetos (como muchos han señalado), y no los recuentos de referencia de bajo nivel per se.

Para concluir: ARC NO es un pase libre para no tener en cuenta la memoria; es una herramienta para ayudar a los humanos a evitar tareas repetitivas, que causan estrés y son propensas al error, por lo tanto mejor delegadas a una máquina (el compilador, en este caso).

Dicho esto, personalmente soy una especie de artesano y aún no he hecho la transición. Acabo de empezar a usar Git ...

ACTUALIZACIÓN: Así que migré todo mi juego, incluida la biblioteca gl, y sin problemas hasta el momento (excepto con el asistente de migración en Xcode 4.2). Si estás comenzando un nuevo proyecto, ve por él.

2

El único inconveniente que he encontrado es si utiliza una biblioteca con muchas funciones y datos de CoreFoundation. En MRC no tenía que preocuparse por usar un CFStringRef en lugar de un NSString*.En ARC, debe especificar cómo interactúan los dos (puente básico? Liberar el objeto CoreFoundation y moverlo a ARC? Hacer un objeto Cocoa como un objeto retenido CoreFoundation +1?) Además, en OS X, solo está disponible en 64- código de bit (aunque tengo un encabezado que funciona alrededor de eso ...).

Cuestiones relacionadas