2012-01-06 21 views
109

Non ho ancora usato ARC, dal momento che la maggior parte del codice nel progetto al quale sto lavorando al momento è stata scritta pre-iOS 5.0.Per ARC o non per ARC? Quali sono i pro e i contro?

Mi stavo chiedendo, la convenienza di non mantenere/rilasciare manualmente (e presumibilmente il codice più affidabile che viene di conseguenza?) Supera ogni "costo" dell'utilizzo di ARC? Quali sono le tue esperienze su ARC e lo consiglieresti?

Quindi:

  • Quanto beneficio può ARC portare a un progetto?
  • ARC ha un costo come la garbage collection in Java?
  • Hai usato ARC e, in tal caso, come l'hai trovato finora?
+0

Non esiste garbage collection su ipad/ios. Stai parlando di OS X? – dasblinkenlight

+1

Le mie scuse, sto usando termini Java out-of-place. Intendo dire che con ARC, gli oggetti possono essere tenuti in memoria più a lungo del necessario, quindi rilasciati come gruppo in un pool di auto-rilascio qualche tempo dopo. È questo effetto di essere mantenuti e rilasciati successivamente con altri oggetti, in modo simile alla raccolta dei rifiuti di Java a cui mi riferisco. –

+3

@TenementFunster, per lo stesso codice (meno le chiamate a rilasciare), ARC terrà l'oggetto non più lungo del codice non ARC. Infatti, spesso lo rilascerà prima di quanto non avresti. Ci sono un piccolo numero di cose che sono un po 'più lente, ma hanno accelerato gli schemi comuni così tanto da minare l'impatto sulle prestazioni. Per molti modelli comuni (conservando un oggetto che è stato restituito con un'autelease, ad esempio), letteralmente non è possibile scriverlo a mano tanto velocemente quanto ARC lo farà automaticamente. –

risposta

145

Non c'è nessun aspetto negativo. Usalo. Fallo oggi. È più veloce del tuo vecchio codice. È più sicuro del tuo vecchio codice. È più facile del tuo vecchio codice. Non è una raccolta di rifiuti. Non ha sovraccarico di runtime di GC. Gli inserimenti del compilatore conservano e rilasciano in tutti i luoghi che dovresti avere comunque. Ma è più intelligente di te e può ottimizzare quelli che non sono realmente necessari (proprio come può srotolare loop, eliminare variabili temporanee, funzioni inline, ecc.)

OK, ora ti parlerò dei piccoli inconvenienti :

  • Se sei un lungo tempo objC sviluppatore, si contrazione per circa una settimana quando si vede il codice ARC. Lo supererai molto rapidamente.

  • Ci sono alcune (molto) piccole complicazioni nel collegarsi al codice della Fondazione Core. Ci sono leggermente più complicazioni nell'affrontare qualcosa che tratta uno id come void*. Cose come i C-array di id possono richiedere un po 'di più di pensare a fare correttamente. Anche la gestione elaborata di ObjC va_args può causare problemi. La maggior parte delle cose che riguardano la matematica su un puntatore ObjC è più complicata. Non dovresti avere molto di questo in ogni caso.

  • Non è possibile inserire id in un struct. Questo è abbastanza raro, ma a volte è usato per impacchettare i dati.

  • Se non è stata eseguita la corretta denominazione KVC e si intermex ARC e codice non ARC, si avranno problemi di memoria. ARC utilizza la denominazione KVC per prendere decisioni sulla gestione della memoria. Se è tutto il codice ARC, allora non importa perché lo farà lo stesso "sbagliato" su entrambi i lati. Ma se è misto ARC/non-ARC, allora c'è una discrepanza.

  • ARC perde memoria durante i lanci di eccezioni ObjC. Un'eccezione ObjC dovrebbe essere molto vicina alla conclusione del programma. Se stai rilevando un numero significativo di eccezioni ObjC, le stai utilizzando in modo errato. Questo è risolvibile mediante -fobjc-arc-exceptions, ma assume le sanzioni discussi di seguito:

  • ARC non perderà la memoria durante objC o C++ eccezione getta nel codice objC++, ma questo è a costo di tempo e spazio prestazioni. Questo è ancora un altro in un lungo elenco di motivi per ridurre al minimo l'utilizzo di ObjC++.

  • ARC non funziona affatto su iPhoneOS 3 o Mac OS X 10.5 o precedente. (Questo mi impedisce di usare ARC in molti progetti.)

  • __weak I puntatori non funzionano correttamente su iOS 4 o Mac OS X 10.6, il che è un peccato, ma è abbastanza facile da aggirare. I puntatori __weak sono ottimi, ma non sono il punto vendita di ARC.

Per il 95% + di codice là fuori, ARC è brillante e non c'è ragione al mondo per evitarlo (fornito è possibile gestire le restrizioni versione del sistema operativo). Per codice non ARC, è possibile passare -fno-objc-arc in base al file. Purtroppo Xcode rende molto più difficile di quanto dovrebbe essere nella pratica. Probabilmente dovresti spostare il codice non ARC in un xcodeproj separato per semplificarlo.

In conclusione, passare a ARC appena possibile e mai guardare indietro.


EDIT

Ho visto un paio di commenti sulla falsariga di "utilizzando ARC è alcun sostituto per conoscere le regole di gestione della memoria di cacao". Questo è principalmente vero, ma è importante capire perché e perché no. Innanzitutto, se tutto il tuo codice utilizza ARC e violerai lo Three Magic Words dappertutto, non avrai ancora problemi. Scioccante da dire, ma ci vai. ARC potrebbe conservare alcune cose che non intendevi mantenere, ma le rilascerà, quindi non avrà mai importanza. Se oggi stavo insegnando una nuova classe in Cocoa, probabilmente non impiegherò più di cinque minuti sulle reali regole di gestione della memoria e probabilmente menzionerei solo le regole di denominazione della gestione della memoria mentre discuto della denominazione KVC. Con ARC, credo che potresti davvero diventare un programmatore principiante decente senza imparare le regole di gestione della memoria.

Ma non è possibile diventare un programmatore intermedio decente. È necessario conoscere le regole per il corretto collegamento con Core Foundation e ogni programmatore intermedio ha bisogno di trattare con CF a un certo punto. E devi conoscere le regole per il codice misto ARC/MRC. E devi conoscere le regole quando inizi a fare scherzi con i puntatori void* su id (che continui a dover eseguire correttamente KVO). E blocchi ... beh, bloccare la gestione della memoria è solo strano.

Quindi il mio punto è che la gestione della memoria sottostante è ancora importante, ma dove passavo molto tempo a dichiarare e rideterminare le regole per i nuovi programmatori, con ARC sta diventando un argomento più avanzato. Preferirei che i nuovi sviluppatori pensassero in termini di oggetti grafici piuttosto che riempire la testa con le chiamate sottostanti a objc_retain().

+0

Grazie per aver dedicato del tempo a scrivere tutto questo Rob - dopo aver letto tutto ciò che le persone hanno scritto qui penso che il più grande ostacolo sarà la mia sfiducia iniziale di lasciare che il compilatore si preoccupi di esso, e forse le mani doloranti dopo aver schiaffeggiato ogni volta che comincio a digitare ret - (scheda) o rel- (scheda)! –

+3

Una cosa a cui prestare molta attenzione (anche in modalità non ARC, ma più complessa in ARC perché è così invisibile ora) è il mantenimento dei cicli. Il mio consiglio qui è 1) se ti trovi a memorizzare un blocco objc come variabile di istanza, osservalo attentamente per vedere se è in grado di catturare l'oggetto di cui è un ivar, anche indirettamente. 2) Realmente progetta il tuo oggetto grafico, piuttosto che lasciarlo accadere. Devi * sapere * cosa possiede cosa se vuoi scrivere un buon codice. 3) Usa heapshots: http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory -growth/ –

+1

@Catfish_Man Tutti i punti positivi. Mantenere i loop è sempre stato un problema. Il nuovo consiglio di Apple è esattamente come dici tu al secondo. Dobbiamo pensare ai grafici degli oggetti piuttosto che conservare e rilasciare. Il n. 1 è un problema serio con i blocchi, e uno dei tanti motivi per cui trovo i blocchi una benedizione mista che dovrebbe essere affrontata con cautela. –

20

meglio, risposte più tecnici del mio arriveranno, ma qui va:!

  • ARC = garbage collection. Non c'è penalità di run time, è fatto in fase di compilazione.
  • ARC anche! = Solo rilasciando automaticamente tutto, come suggerisci nel tuo commento. Leggi la docs
  • È impressionante una volta che si rendono conto di quanto la gestione di riferimento manuale erano facendo
  • Usalo!
  • Uno svantaggio: mantenere il vecchio codice non arcano diventa improvvisamente noioso.
+0

Sì, è per questo che non l'ho usato fino ad ora - non sono sicuro che potrei sopportare di passare attraverso la nostra notevole quantità di codice esistente per convertirlo ... Proverò sicuramente il prossimo progetto però. Grazie per la risposta :) –

+0

Non è che mantenere il vecchio codice diventa più difficile, è che le tue aspettative sono cambiate. Quindi non è giusto incolpare ARC per rendere la vita più facile. Xcode semplifica la conversione del tuo vecchio codice in ARC quando sei pronto, ma ovviamente non puoi utilizzarlo se hai ancora bisogno di supportare versioni iOS più vecchie. – Caleb

+1

@Caleb Non stavo incolpando ARC, è solo l'unico lato negativo che ho visto finora - mi ha rovinato nel marcio di un singolo progetto. – jrturton

2

L'ho usato in un paio di progetti (certamente piccoli), e ho solo buone esperienze, sia in termini di prestazioni che di affidabilità.

Una piccola nota di cautela è che è necessario imparare il do: s e do not: s dei riferimenti deboli per non causare alcun loop di riferimento se si sta codificando l'interfaccia utente da soli, il progettista tende a fare un buon lavoro automaticamente se si imposta la GUI che lo utilizza.

16

Quanti vantaggi può portare ARC a un progetto?

Il vantaggio è un grado significativo di protezione dai comuni errori di gestione della memoria. Le perdite causate dal mancato rilascio di un oggetto e gli arresti anomali a causa del mancato mantenimento o del rilascio prematuro di un oggetto devono essere notevolmente ridotti. È ancora necessario comprendere il modello di memoria conteggiato di riferimento in modo da poter classificare i riferimenti come forti o deboli, evitare i cicli di conservazione e così via.

Quanto costa veramente la "raccolta dei rifiuti"?

Non c'è garbage collection in iOS. ARC è simile a GC in quanto non è necessario conservare manualmente o rilasciare oggetti. Diversamente da GC, non ci sono garbage collector. Il modello di conservazione/rilascio si applica ancora, è solo che il compilatore inserisce le chiamate di gestione della memoria appropriate nel codice per te in fase di compilazione.

Hai usato ARC e, in tal caso, come l'hai trovato finora?

E 'un po' sconcertante, se siete abituati a fare riferimento conteggio, ma questo è solo una questione di abituarsi ad esso e imparare ad avere fiducia che il compilatore sarà davvero fare la cosa giusta. Sembra una continuazione del cambiamento delle proprietà di Objective-C 2.0, un altro grande passo verso la semplificazione della gestione della memoria. Senza le chiamate manuali di gestione della memoria, il codice diventa un po 'più breve e più facile da leggere.

L'unico problema con ARC è che non è supportato nelle versioni precedenti di iOS, quindi è necessario tenerne conto prima di decidere di adottarlo.

+1

C'è la risposta migliore di cui stavo parlando! – jrturton

+1

Sì, ottima risposta. Quindi non c'è davvero alcun svantaggio per ARC oltre a dover imparare a credere che funzioni? Sembra troppo bello per essere vero in quel caso? –

4

Penso che ARC sia una grande idea. Rispetto a GC, puoi avere la tua torta e mangiarla anche tu. Tendo a credere che MRC imponga una "disciplina" inestimabile alla gestione della memoria che tutti potrebbero trarre vantaggio dall'avere. Ma concordo anche sul fatto che il vero problema da tenere presente è la proprietà degli oggetti e i grafici degli oggetti (come molti hanno sottolineato), e non i conteggi di riferimento di basso livello in sé.

Concludendo: ARC NON è un pass gratuito per non pensare alla memoria; è uno strumento per aiutare gli umani a evitare attività ripetitive, che causano stress e sono inclini a errori, quindi meglio delegati a una macchina (il compilatore, in questo caso).

Detto questo, sono personalmente un tipo di artigiano e non ho ancora fatto la transizione. Ho appena iniziato a utilizzare Git ...

AGGIORNAMENTO: Così ho eseguito la migrazione dell'intero gioco, inclusa la gl library, e nessun problema fino ad ora (tranne con l'assistente di migrazione in Xcode 4.2). Se stai iniziando un nuovo progetto, fallo.

2

L'unico svantaggio che ho riscontrato è se si utilizza una libreria con molte funzioni e dati CoreFoundation. In MRC non è necessario preoccuparsi di utilizzare uno CFStringRef anziché uno NSString*.In ARC, devi specificare come interagiscono i due (bridge di base? Rilascia l'oggetto CoreFoundation e spostalo su ARC? Crea un oggetto Cocoa come oggetto mantenuto +1 CoreFoundation?) Inoltre, su OS X, è disponibile solo su 64- codice bit (anche se ho un'intestazione che funziona in quel modo ...).

Problemi correlati