Ad ARC o non ad ARC? Quali sono i pro e i contro? [chiuso]


113

Devo ancora usare ARC, poiché la maggior parte del codice nel progetto a cui sto lavorando al momento è stata scritta prima di iOS 5.0.

Mi stavo solo chiedendo, la comodità di non conservare / rilasciare manualmente (e presumibilmente un codice più affidabile che ne deriva?) Supera il "costo" dell'utilizzo di ARC? Quali sono le tue esperienze con ARC e lo consiglieresti?

Così:

  • Quali vantaggi può portare ARC a un progetto?
  • ARC ha un costo come la garbage collection in Java?
  • Hai usato ARC e, se sì, come l'hai trovato finora?

Non vi è alcuna garbage collection su ipad / ios. Stai parlando di OS X?
dasblinkenlight

1
Mi scuso, sto usando termini Java fuori luogo. Voglio dire che con ARC, gli oggetti possono essere tenuti in memoria più a lungo del necessario, quindi rilasciati come gruppo in un pool di rilascio automatico qualche tempo dopo. È questo l'effetto di mantenerli e rilasciarli con altri oggetti in seguito, in modo simile alla garbage collection di Java a cui mi riferisco.
Simon Withington

3
@TenementFunster, per lo stesso codice (meno le chiamate per il rilascio), ARC manterrà l'oggetto in giro non più del codice non ARC. In effetti, spesso lo rilascerà prima di quanto avresti fatto. Ci sono un piccolo numero di cose che sono un po 'più lente, ma hanno accelerato i modelli comuni così tanto da sminuire l'impatto sulle prestazioni. Per molti modelli comuni (mantenendo un oggetto che è stato restituito con un rilascio automatico, ad esempio), non puoi letteralmente scriverlo a mano velocemente come lo farà ARC automaticamente.
Rob Napier

1
Per quanto riguarda la garbage collection, vedere la mia risposta a questa domanda simile: qual è la differenza tra il conteggio automatico dei riferimenti Objective-C e la garbage collection?
Brad Larson

Risposte:


147

Non ci sono svantaggi. Usalo. Fallo oggi. È più veloce del tuo vecchio codice. È più sicuro del tuo vecchio codice. È più facile del tuo vecchio codice. Non è la raccolta dei rifiuti. Non ha overhead di runtime GC. Il compilatore inserisce conserva e rilascia in tutti i posti che dovresti avere comunque. Ma è più intelligente di te e può ottimizzare quelli che non sono effettivamente necessari (proprio come può srotolare loop, eliminare variabili temporanee, funzioni inline, ecc.)

OK, ora ti parlerò dei piccoli svantaggi:

  • Se sei uno sviluppatore ObjC di lunga data, ti contrarrai per circa una settimana quando vedrai il codice ARC. Lo supererai molto rapidamente.

  • Ci sono alcune (molto) piccole complicazioni nel collegamento al codice Core Foundation. Ci sono un po 'più complicazioni a che fare con tutto ciò che tratta un idcome void*. Cose come C-array di idpossono richiedere un po 'più di riflessione per essere eseguite correttamente. Anche la manipolazione stravagante di ObjC va_argspuò causare problemi. La maggior parte delle cose che coinvolgono la matematica su un puntatore ObjC è più complicata. Non dovresti avere molto di questo in ogni caso.

  • Non si può mettere un idin un struct. Questo è abbastanza raro, ma a volte viene utilizzato per impacchettare i dati.

  • Se non hai seguito la denominazione KVC corretta e mescoli codice ARC e non ARC, avrai problemi di memoria. ARC utilizza la denominazione KVC per prendere decisioni sulla gestione della memoria. Se è tutto codice ARC, non importa perché farà lo stesso "sbagliato" su entrambi i lati. Ma se è misto ARC / non-ARC, allora c'è una mancata corrispondenza.

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

  • ARC non perderà memoria durante le eccezioni ObjC o C ++ nel codice ObjC ++, ma ciò è a scapito delle prestazioni di tempo e spazio. Questo è ancora un altro in un lungo elenco di motivi per ridurre al minimo l'utilizzo di ObjC ++.

  • ARC non funzionerà affatto su iPhoneOS 3 o Mac OS X 10.5 o versioni precedenti. (Questo mi impedisce di utilizzare ARC in molti progetti.)

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

Per il 95% + del codice disponibile, ARC è eccezionale e non c'è alcun motivo per evitarlo (a condizione che tu possa gestire le restrizioni della versione del sistema operativo). Per il codice non ARC, è possibile passare -fno-objc-arcfile per file. Xcode purtroppo rende questo molto più difficile di quanto dovrebbe essere in pratica. Probabilmente dovresti spostare il codice non ARC in un xcodeproj separato per semplificarlo.

In conclusione, passa ad ARC il prima possibile e non guardarti mai indietro.


MODIFICARE

Ho visto un paio di commenti sulla falsariga di "l'utilizzo di ARC non è un sostituto per conoscere le regole di gestione della memoria Cocoa". Questo è per lo più vero, ma è importante capire perché e perché no. Innanzitutto, se tutto il codice utilizza ARC e si violano le tre parole magicheovunque, non avrai ancora problemi. Scioccante da dire, ma eccoti. ARC potrebbe conservare alcune cose che non volevi conservare, ma rilascerà anche quelle, quindi non avrà mai importanza. Se oggi insegnassi una nuova classe a Cocoa, probabilmente non spenderei più di cinque minuti sulle effettive regole di gestione della memoria, e probabilmente menzionerei solo le regole di denominazione per la gestione della memoria mentre discuto dei nomi KVC. Con ARC, credo che potresti diventare un programmatore principiante decente senza imparare affatto le regole di gestione della memoria.

Ma non potresti diventare un programmatore intermedio decente. È necessario conoscere le regole per creare un collegamento corretto con Core Foundation e ogni programmatore intermedio deve affrontare la CF ad un certo punto. Ed è necessario conoscere le regole per il codice misto ARC / MRC. E devi conoscere le regole quando inizi a scherzare con i void*puntatori id(a cui continui a essere necessario per eseguire correttamente KVO). E i blocchi ... beh, la gestione della memoria a blocchi è semplicemente strana.

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


3
Una cosa a cui stare molto attenti (anche non in ARC, ma di più in ARC perché ora è così invisibile) è mantenere i cicli. Il mio consiglio qui è 1) se ti ritrovi a memorizzare un blocco objc come variabile di istanza, esaminalo a lungo per vedere se potrebbe catturare l'oggetto di cui è un ivar, anche indirettamente. 2) In realtà progetta il tuo oggetto grafico, piuttosto che lasciarlo semplicemente accadere. È necessario sapere che cosa possiede cosa se si vuole scrivere del buon codice. 3) Usa heapshots: friday.com/bbum/2010/10/17/…
Catfish_Man

1
@Catfish_Man Tutti i punti positivi. I loop di mantenimento sono sempre stati un problema. Il nuovo consiglio di Apple è esattamente come dici al punto 2. Dobbiamo pensare agli oggetti grafici piuttosto che trattenerli e rilasciarli. # 1 è un problema serio con i blocchi e uno dei diversi motivi per cui trovo i blocchi una benedizione mista che dovrebbe essere affrontata con cautela.
Rob Napier

2
C'è un grave svantaggio che non è stato menzionato: la compatibilità incrociata. Per noi anime coraggiose e folli che affrontano le terre desolate conosciute come programmazione multipiattaforma, ARC semplicemente non è un'opzione, almeno non fino a quando GNU non espanderà nuovamente il loro runtime ObjC e le funzionalità del compilatore (dicono che altro è in arrivo).
Coniglio

2
Puoi usare ARC tranne per il fatto che devi supportare i dispositivi iOS 3.x. A proposito, assicurati di utilizzare Xcode per eseguire la transizione (Modifica> Refactor> Converti in Objective-C ARC). Durante il processo Xcode eseguirà molte convalide per assicurarsi che il codice funzioni e individuare eventuali codici che violano le linee guida di progettazione.
ZhangChn

1
Eccellente .. rispondi puntualmente. da me è il centesimo. Congratulazioni per un secolo;)
Ajay Sharma

20

Verranno risposte migliori e più tecniche delle mie, ma ecco qui:

  • ARC! = Garbage Collection. Non è prevista alcuna penalità per il tempo di esecuzione, viene eseguita in fase di compilazione.
  • Anche ARC! = Rilascia tutto automaticamente, come suggerisci nel tuo commento. Leggi i documenti
  • E 'impressionante una volta che si rendono conto di quanto la gestione manuale di riferimento si stavano facendo
  • Usalo!
  • Uno svantaggio: mantenere il vecchio codice senza arco diventa improvvisamente molto noioso.

Sì, è per questo che non l'ho usato finora - Non sono sicuro di poter sopportare di passare attraverso la nostra notevole quantità di codice preesistente per convertirlo ... Lo proverò sicuramente nel prossimo progetto. Grazie per la tua risposta :)
Simon Withington

Non è che mantenere il vecchio codice diventi più difficile, è che le tue aspettative sono cambiate. Quindi non è davvero giusto incolpare ARC per aver reso la vita più facile. Xcode semplifica la conversione del vecchio codice in ARC quando sei pronto, ma ovviamente non puoi usarlo se devi ancora supportare le versioni iOS precedenti.
Caleb

1
@Caleb Non stavo incolpando ARC, è solo che questo è l'unico aspetto negativo che ho visto finora: mi ha rovinato a marcire nello spazio di un singolo progetto.
jrturton

Si; Non l'ho elencato come un problema, ma c'è un piccolo problema di uscire dalla pratica di gestione della memoria quando devi passare da una base di codice a un'altra. Alcuni dei miei progetti girano sulla 10.4, quindi lavoro ancora molto con Objective-C 1.0 (quindi niente @synthesize, figuriamoci ARC). Ma ti abitui a cambiare modalità abbastanza bene.
Rob Napier

@jrturton Avrei dovuto chiarire che l'ho scritto a beneficio dell'OP e dei futuri lettori che potrebbero non capire cosa fa ARC. So esattamente cosa intendi, semplicemente non volevo che nessuno trasse la conclusione sbagliata che mescolare codice ARC e non ARC crea un problema.
Caleb

16

Quali 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 dovuti alla mancata conservazione o al rilascio prematuro di un oggetto dovrebbero essere notevolmente ridotti. È ancora necessario comprendere il modello di memoria conteggio dei riferimenti in modo da poter classificare i riferimenti come forti o deboli, evitare cicli di conservazione e così via.

Quanto "costa" realmente la raccolta dei rifiuti?

Non è presente la raccolta dei rifiuti in iOS. ARC è simile a GC in quanto non è necessario conservare o rilasciare manualmente gli oggetti. È diverso da GC in quanto non esiste un 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, se sì, come l'hai trovato finora?

È un po 'sconcertante se sei abituato a fare riferimento al conteggio, ma è solo questione di abituarti e imparare a credere che il compilatore farà davvero la cosa giusta. Sembra una continuazione del cambiamento alle proprietà fornito con Objective-C 2.0, che è stato un altro grande passo verso la semplificazione della gestione della memoria. Senza le chiamate di gestione della memoria manuale, 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 inconveniente in ARC oltre a dover imparare a fidarsi che funzioni? Sembra troppo bello per essere vero in quel caso?
Simon Withington

4

Penso che ARC sia un'ottima idea. Rispetto a GC, puoi avere la tua torta e mangiarla anche tu. Tendo a credere che MRC imponga una "disciplina" inestimabile verso la gestione della memoria che tutti trarrebbero vantaggio dall'avere. Ma sono anche d'accordo sul fatto che il vero problema di cui essere consapevoli è la proprietà degli oggetti e i grafici degli oggetti (come molti hanno sottolineato) e non i conteggi di riferimento di basso livello di per sé.

Per concludere: ARC NON è un pass gratuito per non pensare alla memoria; è uno strumento per aiutare gli esseri umani a evitare compiti ripetitivi, che causano stress e sono soggetti a errori, quindi meglio delegati a una macchina (il compilatore, in questo caso).

Detto questo, personalmente sono una specie di artigiano e non ho ancora effettuato la transizione. Ho appena iniziato a usare Git ...

AGGIORNAMENTO: Quindi ho migrato tutto il mio gioco, libreria gl inclusa, 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'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 devi imparare le cose da fare e da non fare dei riferimenti deboli per non causare alcun loop di riferimento se stai codificando la tua interfaccia utente da solo, il progettista tende a fare un buon lavoro automaticamente se imposti la tua GUI usandola.


2

L'unico svantaggio che ho riscontrato è se utilizzi una libreria con molte funzioni e dati CoreFoundation. In MRC non era necessario preoccuparsi di utilizzare un CFStringRefinvece di un file NSString*. In ARC, devi specificare come i due interagiscono (bridge di base? Rilasciare l'oggetto CoreFoundation e spostarlo su ARC? Creare un oggetto Cocoa come oggetto trattenuto da CoreFoundation +1?) Inoltre, su OS X, è disponibile solo su 64- codice bit (anche se ho un'intestazione che funziona intorno a questo ...).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.