2012-05-13 26 views

risposta

21

Come per le altre ottimizzazioni delle prestazioni, in genere è necessario aggiungere ulteriori pool di autorelease al codice se si nota un utilizzo e una profilazione della memoria elevati (utilizzando Strumenti, ad esempio) come pool di pool di autorelease aggiuntivi.

Detto questo, è possibile inserire il codice che crea un numero elevato di oggetti temporanei in un ciclo stretto in un pool di autorelease. Il pool di autorelease predefinito viene scaricato alla fine di un ciclo del ciclo di esecuzione. Quindi, se stai creando molti oggetti temporanei in ogni iterazione di un ciclo for nel tuo codice, il pool di autorelease predefinito non verrà scaricato fino a quando non verrà eseguito l'intero ciclo, il che significa che tutti gli oggetti temporanei che crei possono sommarsi un elevato utilizzo di memoria temporanea (a volte chiamato "high water mark"). È possibile eseguire il wrapping di ogni iterazione del ciclo in un @autoreleasepool per causare gli oggetti temporanei non autorizzati, con autorizzazione automatica, creati in tale iterazione da rilasciare prima.

+0

Mi hai salvato. Ho un metodo di calcolo a lungo termine che crea molti numeri in più loop. Negli strumenti, l'utilizzo della memoria sale tremendamente e si riduce al termine del calcolo. C'è uno svantaggio usando '@ autorelease' per avvolgere i singoli loop? Non è davvero raccomandato da Apple, vero? – JFS

+2

È consigliato da Apple nei casi in cui è appropriato. Vedere la documentazione qui: https://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html –

+0

Andrew, sei semplicemente fantastico! Ho avuto un mal di testa a causa di quel problema di memoria fino a quando non ho trovato questo suggerimento. È semplice e funziona semplicemente fantastico. Posso anche consentire più calcoli nella mia app ora. GRAZIE! – JFS

1

Tutti gli oggetti autoreleased sono messi tecnicamente all'interno di un pool di autorelease. Di solito c'è uno di default creato all'interno della tua funzione principale. Per quanto riguarda il wrapping di oggetti all'interno di un pool di autorelease non predefinito, questo viene solitamente eseguito come ottimizzazione.

Di solito non è necessario utilizzare un pool di autorelease esplicito perché il pool di autorelease predefinito viene scaricato automaticamente all'interno del ciclo di esecuzione dell'app. Tuttavia, se si dispone di un'app che crea molti oggetti autoreleased prima che ritorni dai gestori di eventi, può utilizzare molta memoria per tali oggetti. Quindi, se si avvolge il codice all'interno di un pool di autoritease esplicito, gli oggetti autoreleased verranno posizionati lì anziché il pool predefinito. Ciò consente di svuotare periodicamente questo pool per impedire l'accumulo degli oggetti autoreleased.

12

Per estende le risposte precedenti:

una piscina auto-rilascio viene utilizzato per inviare automaticamente un messaggio release agli oggetti aggiunti ad esso.

In un programma iOS o Cocoa, viene creato automaticamente un pool di rilascio automatico sul thread principale, che viene scaricato alla fine del ciclo di esecuzione.

Detto questo, un pool di rilascio automatico è obbligatorio quando si utilizzano oggetti rilasciati automaticamente su un altro thread.

Quindi se si scollega un thread con un metodo, quindi si avvolge il codice filettato all'interno di un pool di rilascio automatico. Altrimenti, gli oggetti auto-rilasciati creati nel thread saranno solo perdite.

Un altro utilizzo di un pool di rilascio automatico è l'ottimizzazione di parti di codice che utilizzeranno molta memoria, quindi vengono liberate prima della fine del ciclo di esecuzione.

Ma riguarda solo gli oggetti rilasciati automaticamente.

Per esempio:

- (void)test 
{ 
    NSMutableArray * a = [ [ NSMutableArray alloc ] init ]; 

    [ a release ]; 
} 

Non c'è bisogno di una piscina auto-stampa qui, come non si dispone di un oggetto auto-rilasciato.
La variabile a verrà liberata immediatamente, poiché è stata allocata in modo esplicito e rilasciata.

Ora questo:

- (void)test 
{ 
    NSMutableArray * a = [ NSMutableArray arrayWithCapacity ]; 
} 

Qui si utilizza un costruttore convenienza, il che significa che non si ha la proprietà su tale oggetto.
Significa anche che l'oggetto è stato aggiunto al pool di rilascio automatico corrente (se ce n'è uno).

Così sarà liberato quando questo pool di auto-rilascio viene scaricata, quindi potrebbe prendere alcuni cicli ...

Se la parte di codice che si sta scrivendo utilizza un sacco di memoria, è possibile utilizzare un altro piscina autorelease, quindi gli oggetti auto-rilasciati vengono liberate quando il vostro metodo ritorna:

- (void)test 
{ 
    @autoreleasepool 
    { 
     NSMutableArray * a = [ NSMutableArray arrayWithCapacity ]; 
    } 
} 
0

ci sono, tuttavia, tre occasioni in cui si potrebbe utilizzare i propri blocchi piscina autorelease:

  1. Se si sta scrivendo un programma che non è basato su un framework UI, come uno strumento da riga di comando.

  2. Se si scrive un ciclo che crea molti oggetti temporanei. È possibile utilizzare un blocco pool autorelease all'interno del ciclo per smaltire tali oggetti prima della successiva iterazione. L'utilizzo di un blocco pool autorelease nel loop aiuta a ridurre il massimo ingombro di memoria dell'applicazione.

  3. Se si genera un thread secondario.

Problemi correlati