19

Diciamo che ho un ciclo che restituisce un po 'di oggetti NSData autoreleased ...Sotto ARC, è comunque consigliabile creare un @autoreleasepool per i loop?

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

Sotto ARC, devo ancora avvolgere un @autoreleasepool intorno la condizione while?

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

Il motivo per cui sto chiedendo è che vedo il conteggio allocazione vivono in strumenti che passano attraverso il tetto per i miei oggetti NSData che richiamano un metodo dataWith... al contrario di un metodo di initWith.... Quando uso initWith..., il conteggio delle allocazioni vive è molto, molto meno.

È preferibile preferire i metodi initWith... quando possibile?

risposta

13

Sì, è necessario utilizzare i pool di autorelease quando si utilizzano i metodi di convenienza in un ciclo stretto. Tutte le vecchie regole di gestione della memoria si applicano ancora sotto ARC, il compilatore sta semplicemente iniettando RR per te. Scopri il fantastico post del fantastico Mike Ash!

Link

+0

Grazie per l'ottimo collegamento! –

+10

Per @ risposta di Chuck: @autoreleasepool deve andare * all'interno * del ciclo per fare qualcosa di buono. L'idioma è 'while (x) @autoreleasepool {...}', non '@autoreleasepool {while (x) {...}}'. – Quuxplusone

+0

Questo è semplificato e scorretto. ARC può spesso ottimizzare l'uso del pool autorelease per i metodi che restituiscono un oggetto +0 (che è l'uso più frequente di "autorelease"). –

7

Sotto ARC, dovrei ancora avvolgere un @autoreleasepool intorno alla condizione, mentre?

Sì. I pool Autorelease sono ancora in funzione, e crescono e scoppiano come prima. Il compilatore aggiunge e raggruppa le necessarie operazioni di conservazione e rilascio quando ARC è abilitato (eco Logan), in base ai metodi che sono visibili alla TU e alle convenzioni di denominazione predefinite.

L'esecuzione in ARC è quasi identica al conteggio del riferimento manuale: le pile di pool Autorelease esistono ancora. Una differenza è che il compilatore può ordinare le operazioni di conteggio dei riferimenti in modo leggermente diverso dal modo in cui è stato scritto (non in modo errato) e può omettere cicli di conservazione non necessari.

E 'meglio preferire i initWith ... metodi quando possibile?

WRT minimizzare la crescita dell'heap rispetto alle controparti autorizzate: Sì. È sempre stato così. È particolarmente importante sui dispositivi iOS, dove la memoria è piuttosto limitata.

L'eccezione è quando l'oggetto può evitare un'allocazione. Esempio:

NSString * copy = [NSString stringWithString:arg]; 

in questo caso, può essere copy[[arg retain] autorelease]. Nota che in questo caso, copy è ancora autorizzato automaticamente, ma di solito non dovresti fare di tutto per verificare la presenza di tali ottimizzazioni. Nota: è anche meglio usare copy = [arg copy] ... [arg release] qui.

L'altro bonus è che gli squilibri di conteggio ref vengono spesso rilevati in precedenza quando l'oggetto non viene mai rilasciato automaticamente e più vicino al sito di chiamata (piuttosto che quando il pool di autorelease è finalmente spuntato).

Le prestazioni con vasche di autoregenerazione di grandi dimensioni sono in realtà molto peggiori di quanto supponiamo la maggior parte delle persone. Se puoi evitare di dipendere da loro pesantemente (ad esempio utilizzando alloc + init ...+ release), puoi rendere il tuo programma notevolmente più veloce. La creazione esplicita di pool di autorelease è economica e può aiutare a minimizzare questo problema. Quando le allocazioni sono grandi e/o numerose, evitare di utilizzare autorelease su di esse laddove possibile e avvolgere queste sezioni in pool di autorespirazione espliciti.

13

Penso che il problema sia che il pool di autorelease deve passare al all'interno del ciclo. Con il ciclo all'interno del blocco di autorelease anziché viceversa, gli oggetti accumulati non verranno rilasciati fino al termine del ciclo.

+0

Non ho pensato di inserire '@ autoreleasepool' nel loop ... grazie per il suggerimento. –