¿A ARC o no a ARC? ¿Cuáles son los pros y los contras? [cerrado]

113

Todavía tengo que usar ARC, ya que la mayor parte del código del proyecto en el que estoy trabajando en este momento fue escrito antes de iOS 5.0.

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

Entonces:

  • ¿Cuánto beneficio puede aportar ARC a un proyecto?
  • ¿ARC tiene un costo como la recolección de basura en Java?
  • ¿Ha estado usando ARC y, de ser así, cómo lo ha encontrado hasta ahora?
Simon Withington
fuente
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. Quiero decir que con ARC, los objetos se pueden mantener en la memoria durante más tiempo del necesario y luego se pueden liberar como grupo en un grupo de liberación automática algún tiempo después. Es este efecto de mantenerlos y liberarlos con otros objetos más tarde, de manera similar a la recolección de basura de Java a la que me refiero.
Simon Withington
3
@TenementFunster, para el mismo código (menos las llamadas a liberar), ARC no mantendrá el objeto alrededor del código que no sea ARC. De hecho, a menudo lo publicará antes de lo que lo haría. Hay una pequeña cantidad de cosas que son algo más lentas, pero aceleraron tanto los patrones comunes que empequeñece el impacto en el rendimiento. Para muchos patrones comunes (retener un objeto que se devolvió con una liberación automática, por ejemplo), literalmente no puede escribirlo a mano tan rápido como ARC lo hará automáticamente.
Rob Napier
1
Con respecto a la recolección de basura, vea mi respuesta a esta pregunta similar: ¿Cuál es la diferencia entre el recuento automático de referencias de Objective-C y la recolección de basura?
Brad Larson

Respuestas:

147

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

Bien, ahora les contaré los pequeños inconvenientes:

  • Si es un desarrollador de ObjC desde hace mucho tiempo, se contraerá durante aproximadamente una semana cuando vea el código ARC. Lo superarás muy rápidamente.

  • Hay algunas (muy) pequeñas complicaciones en la conexión al código de Core Foundation. Hay poco más complicaciones en el trato con todo lo que trata una idcomo void*. Cosas como las matrices C de idpueden requerir un poco más de reflexión para hacerlas correctamente. El manejo elegante de ObjC va_argstambién puede causar problemas. La mayoría de las cosas que involucran matemáticas en un puntero ObjC son más complicadas. No debería tener mucho de esto en cualquier caso.

  • No se puede poner iden una struct. Esto es bastante raro, pero a veces se usa para empaquetar datos.

  • Si no siguió la denominación correcta de KVC y mezcla código ARC y no ARC, tendrá problemas de memoria. ARC utiliza la denominación KVC para tomar decisiones sobre la gestión de la memoria. Si todo es código ARC, entonces no importa porque hará lo mismo "mal" en ambos lados. Pero si se trata de una mezcla ARC / no ARC, entonces hay una falta de coincidencia.

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

  • ARC no perderá memoria durante las excepciones de ObjC o C ++ en código ObjC ++, pero esto es a costa del rendimiento de tiempo y espacio. Esta es otra de 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 anterior. (Esto me impide usar ARC en muchos proyectos).

  • __weaklos punteros no funcionan correctamente en iOS 4 o Mac OS X 10.6, lo cual es una pena, pero es bastante fácil de solucionar. __weakLos consejos son geniales, pero no son el punto de venta número uno de ARC.

Para más del 95% del código, ARC es brillante y no hay ninguna razón para evitarlo (siempre que pueda manejar las restricciones de la versión del sistema operativo). Para el código que no es ARC, puede pasar -fno-objc-arcarchivo 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ía mover código que no es ARC a un xcodeproj separado para simplificar esto.

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


EDITAR

He visto un par de comentarios en la línea de "usar ARC no sustituye a conocer las reglas de administración de memoria de Cocoa". Esto es mayormente cierto, pero es importante entender por qué y por qué no. Primero, si todo su código usa ARC y viola las Tres Palabras Mágicaspor todas partes, todavía no tendrás problemas. Es impactante decirlo, pero ahí lo tienes. ARC puede retener algunas cosas que no querías que retenga, pero también las liberará, 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 reales de administración de la memoria, y probablemente solo mencionaría las reglas de administración de la memoria para nombrar al hablar sobre los nombres de KVC. Con ARC, creo que podría convertirse en un programador principiante decente sin tener que aprender las reglas de administración de la memoria.

Pero no podrías convertirte en un programador intermedio decente. Necesita conocer las reglas para conectarse correctamente con Core Foundation, y cada programador intermedio necesita lidiar con CF en algún momento. Y necesita conocer las reglas para el código ARC / MRC mixto. Y necesita conocer las reglas cuando empiece a jugar con los void*punteros id(que sigue necesitando para realizar KVO correctamente). Y bloques ... bueno, la gestión de la memoria en bloque es simplemente extraña.

Entonces, mi punto es que la administración de la memoria subyacente sigue siendo importante, pero donde solía pasar mucho tiempo estableciendo y reformulando 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 a objc_retain().

Rob Napier
fuente
3
Una cosa con la que hay que tener mucho cuidado (también en los que no son ARC, pero más en ARC porque ahora es tan invisible) es la retención de ciclos. Mi consejo aquí es 1) si se encuentra almacenando un bloque objc como una variable de instancia, examínelo detenidamente para ver si puede capturar el objeto del que es un ivar, incluso indirectamente. 2) Realmente diseñe su gráfico de objetos, en lugar de dejar que suceda. Usted debe saber lo que es dueño de qué, si desea escribir un buen código. 3) Use heapshots: friday.com/bbum/2010/10/17/…
Catfish_Man
1
@Catfish_Man Todos los buenos puntos. Los bucles de retención siempre han sido un problema. El nuevo consejo de Apple es exactamente como dice en el n. ° 2. Necesitamos pensar en gráficos de objetos en lugar de retener y liberar. El # 1 es un problema serio con los bloques, y una de las varias razones por las que encuentro que los bloques son una bendición mixta que debería abordarse con precaución.
Rob Napier
2
Hay una desventaja seria que no se mencionó: compatibilidad cruzada. Para nosotros, almas valientes y tontas que nos enfrentamos a los páramos conocidos como programación multiplataforma, ARC simplemente no es una opción, al menos no hasta que GNU expanda su tiempo de ejecución de ObjC y las características del compilador nuevamente (dicen que hay más en camino).
Conejo
2
Puede usar ARC excepto que necesita ser compatible con dispositivos iOS 3.x. Por cierto, asegúrese de usar Xcode para hacer la transición (Editar> Refactorizar> Convertir a Objective-C ARC). Durante el proceso, Xcode haría una gran cantidad de validación para asegurarse de que su código funcione y descubra cualquier código que viole esas pautas de diseño.
ZhangChn
1
Excelente .. respuesta puntual. eso es 100 de mi parte. Felicidades por un siglo;)
Ajay Sharma
20

Llegarán respuestas mejores y más técnicas que las mías, pero aquí va:

  • ARC! = Recolección de basura. No hay penalización por tiempo de ejecución, se realiza en tiempo de compilación.
  • ¡ARC también! = Simplemente liberando todo automáticamente, como sugieres en tu comentario. Leer los documentos
  • Es increíble una vez que te das cuenta de la cantidad de gestión manual de referencias que estabas haciendo
  • ¡Úsalo!
  • Un inconveniente: mantener un código antiguo que no es de arco de repente se vuelve muy tedioso.
jrturton
fuente
Sí, es por eso que no lo he usado hasta ahora; no estoy seguro de poder soportar revisar nuestra cantidad sustancial de código preexistente para convertirlo ... Sin embargo, definitivamente lo probaré en el próximo proyecto. Gracias por tu respuesta :)
Simon Withington
No es que mantener el código antiguo se vuelva más difícil, es que sus expectativas han cambiado. Por tanto, no es justo culpar a ARC por hacer la vida más fácil. Xcode facilita la conversión de su código anterior a ARC cuando esté listo, pero obviamente no puede usarlo si aún necesita admitir versiones anteriores de iOS.
Caleb
1
@Caleb No estaba culpando a ARC, es solo que ese es el único inconveniente que he visto hasta ahora: me ha echado a perder en el espacio de un solo proyecto.
jrturton
Si; No mencioné eso como un problema, pero hay un pequeño problema de salir de la práctica de administración de memoria cuando tienes que cambiar entre bases de código. Algunos de mis proyectos se ejecutan en 10.4, por lo que todavía hago mucho trabajo en Objective-C 1.0 (por lo que no @synthesize, y mucho menos ARC). Pero te acostumbras bastante bien a cambiar de modo.
Rob Napier
@jrturton Debería haber dejado más claro que escribí eso en beneficio del OP y de los futuros lectores que pueden no entender lo que hace ARC. Sé exactamente lo que quieres decir, simplemente no quería que nadie llegara a la conclusión errónea de que mezclar código ARC y no ARC crea un problema.
Caleb
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 no liberar un objeto y los choques por no retener o liberar prematuramente un objeto deben reducirse significativamente. Aún necesita comprender el modelo de memoria contada de referencia para poder clasificar sus referencias como fuertes o débiles, evitar ciclos de retención, etc.

¿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. Es diferente a GC en que no hay recolector de basura. El modelo de retención / liberación aún se aplica, es solo que el compilador inserta las llamadas de administración de memoria adecuadas en su código en el momento de la compilación.

¿Ha estado usando ARC y, de ser así, cómo lo ha encontrado hasta ahora?

Es un poco desconcertante si está acostumbrado al conteo de referencias, pero eso es solo una cuestión de acostumbrarse y aprender a confiar en que el compilador realmente hará lo correcto. Se siente como una continuación del cambio a las propiedades que venía 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 versiones anteriores de iOS, por lo que debe tenerlo en cuenta antes de decidir adoptarlo.

Caleb
fuente
1
¡Esa es la mejor respuesta de la que estaba hablando!
jrturton
1
Sí, gran respuesta. Entonces, ¿realmente no hay ningún inconveniente para ARC además de tener que aprender a confiar en que funciona? ¿Parece demasiado bueno para ser verdad en ese caso?
Simon Withington
4

Creo que ARC es una gran idea. En comparación con GC, puedes tener tu pastel y comértelo también. Tiendo a creer que MRC impone una "disciplina" invaluable 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 a errores, por lo que es mejor delegarla en 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 hasta ahora no tuve problemas (excepto con el asistente de migración en Xcode 4.2). Si está comenzando un nuevo proyecto, hágalo.

Nicolas Miari
fuente
2

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

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

Joachim Isaksson
fuente
2

El único inconveniente que he encontrado es si usa una biblioteca con muchas funciones y datos de CoreFoundation. En MRC no tenía que preocuparse por usar un en CFStringReflugar 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 +1 CoreFoundation?) Además, en OS X, solo está disponible en 64- código de bits (aunque tengo un encabezado que funciona alrededor de eso ...).

MaddTheSane
fuente