objective-c memory-management automatic-ref-counting nsautoreleasepool

objective c - Bajo ARC, ¿sigue siendo recomendable crear un @autoreleasepool para bucles?



objective-c memory-management (3)

Digamos que tengo un bucle que devuelve un montón de objetos NSData lanzados automáticamente ...

NSData* bigData = ... while(some condition) { NSData* smallData = [bigData subdataWithRange:...]; //process smallData }

Debajo de ARC, ¿todavía debería envolver un @autoreleasepool alrededor de la condición while ?

NSData* bigData = ... @autoreleasepool { while(some condition) { NSData* smallData = [bigData subdataWithRange:...]; //process smallData } }

La razón por la que pregunto es que veo la cantidad de asignaciones de vida en instrumentos que pasan por el techo para mis objetos NSData que invocan un método dataWith... en lugar de un método initWith... Cuando uso initWith... , el recuento de asignación de vida es mucho, mucho menos.

¿Es mejor preferir los métodos initWith... siempre que sea posible?


Debajo de ARC, ¿todavía debería envolver un @autoreleasepool alrededor de la condición while?

Sí. Autorelease Pools todavía están en su lugar, y crecen y explotan como antes. El compilador simplemente agrega y une las retenciones y operaciones necesarias cuando ARC está habilitado (haciendo eco de Logan), según los métodos que son visibles para la TU y las convenciones de nomenclatura predeterminadas.

La ejecución en ARC es casi idéntica al recuento manual de referencias: las pilas de agrupación de liberación automática todavía existen. Una diferencia es que el compilador puede ordenar las operaciones de conteo de referencias ligeramente diferentes de la forma en que lo escribió (no de manera incorrecta), y puede omitir ciclos de retención innecesarios.

¿Es mejor preferir los métodos initWith ... siempre que sea posible?

WRT minimiza el crecimiento de la pila en comparación con las contrapartes lanzadas automáticamente: Sí. Ese ha sido siempre el caso. Es especialmente importante en dispositivos iOS, donde la memoria es bastante limitada.

La excepción a esto es cuando el objeto puede evitar una asignación. Ejemplo:

NSString * copy = [NSString stringWithString:arg];

en este caso, la copy puede ser [[arg retain] autorelease] . Tenga en cuenta que, en este caso, la copy aún se publica automáticamente, pero generalmente no debe hacer un gran esfuerzo para probar la presencia de tales optimizaciones. Nota: también es mejor usar copy = [arg copy] ... [arg release] aquí.

La otra ventaja es que los desequilibrios de recuento de referencia a menudo se detectan antes cuando el objeto nunca se lanza automáticamente, y más cerca del sitio de la llamada (en lugar de cuando finalmente se abre el Grupo de Autorelease).

El rendimiento con grandes grupos de autorelease es en realidad mucho peor de lo que la mayoría de las personas suponen. Si puede evitar depender mucho de ellos (p. Ej., El uso de alloc + init ... + release ), puede hacer que su programa sea notablemente más rápido. La creación explícita de grupos de autorelease es barata y puede ayudar a minimizar este problema. Cuando las asignaciones son grandes y / o numerosas, evite usar el autorelease en ellas cuando sea posible, y envuelva estas secciones en grupos explícitos de autorelease.


Creo que su problema es que el grupo de autorelease debe ir dentro del bucle. Con el bucle dentro del bloque de liberación automática en lugar de viceversa, los objetos acumulados no se liberarán hasta que finalice el bucle.


Sí, aún debe utilizar los grupos de autorelease cuando se utilizan métodos de conveniencia en un circuito cerrado. Todas las reglas de administración de memoria antiguas aún se aplican bajo ARC, el compilador simplemente está inyectando RR para usted. Echa un vistazo a la gran publicación por el impresionante Mike Ash!

Link