19

Digamos que tengo un bucle que devuelve un conjunto de objetos NSData autoreleased ...En ARC, ¿aún así es aconsejable crear un @autoreleasepool para bucles?

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

Bajo ARC, debe todavía envolver un @autoreleasepool torno a la condición while?

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

La razón por la que te pido es que veo la cuenta de asignación de estar en los instrumentos que van a través del techo para mis objetos NSData que invocan un método dataWith... en contraposición a un método initWith.... Cuando uso initWith..., el conteo de asignación de vida es mucho, mucho menos.

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

Respuesta

13

Sí, aún debe utilizar grupos de liberación automática cuando utiliza métodos de conveniencia en un ciclo cerrado. Todas las viejas reglas de administración de memoria aún se aplican bajo ARC, el compilador simplemente está inyectando RR por usted. ¡Mira la gran publicación del impresionante Mike Ash!

Link

+0

¡Gracias por el gran enlace! –

+10

Respuesta de Per @ Chuck: el @autoreleasepool necesita ir * dentro * del bucle para que le sirva de algo. La expresión idiomática es 'while (x) @autoreleasepool {...}', no '@autoreleasepool {while (x) {...}}'. – Quuxplusone

+0

Esto es demasiado simplista e incorrecto. ARC a menudo puede optimizar el uso de distancia del grupo de autorrelease para los métodos que devuelven un objeto +0 (que es el uso más frecuente del uso de 'autorelease'). –

7

Bajo ARC, debería todavía envolver un @autoreleasepool en torno a la condición de tiempo?

Sí. Las piscinas de Autorelease todavía están en su lugar, y crecen y explotan como antes. El compilador simplemente agrega y combina las operaciones de retención y liberación necesarias cuando ARC está habilitado (haciéndose 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 a la del recuento manual de referencias: todavía existen pilas de agrupaciones de almacenamiento automático. Una diferencia es que el compilador puede ordenar las operaciones de recuento de referencia ligeramente diferentes a la forma en que lo escribió (no de forma incorrecta), y puede omitir ciclos de retención innecesarios.

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

WRT crecimiento minimizando montón en comparación con las contrapartes autoreleased: Si. Ese siempre ha sido 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, copy puede ser [[arg retain] autorelease]. Tenga en cuenta que en este caso, copy todavía se libera automáticamente, pero no debe hacer grandes esfuerzos 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 referencia se suelen detectar antes cuando el objeto nunca se libera automáticamente, y más cerca del sitio de llamada (en lugar de cuando finalmente se abre el Pool Autorelease).

El rendimiento con grandes pools de liberación automática es en realidad mucho peor de lo que la mayoría de la gente supondría. Si puede evitar depender mucho de ellos (por ejemplo, usando alloc + init ...+ release), puede hacer que su programa sea notablemente más rápido. La creación explícita de grupos de liberación automática es económica y puede ayudar a minimizar este problema. Cuando las asignaciones son grandes y/o numerosas, evite usar autorelease en ellas siempre que sea posible, y ajuste estas secciones en conjuntos de autorreleases explícitos.

13

Creo que su problema es que el grupo de liberación automática se supone que va a dentro de el 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 termine el bucle.

+0

No he pensado poner el '@ autoreleasepool' dentro del circuito ... gracias por la sugerencia. –

Cuestiones relacionadas