29

riferimento Grand Central Dispatch di Apple dice:Perché dovrei scegliere GCD su NSOperation e blocchi per applicazioni di alto livello?

" ... se l'applicazione deve operare a livello di Unix dell'esempio sistema per , se ha bisogno di manipolare i descrittori di file, Mach porte, segnali o GCD non è limitato alle applicazioni a livello di sistema , ma prima di utilizzarlo per applicazioni di livello superiore, è necessario considerare se la funzionalità simile fornita in Cocoa (tramite NSOperation e oggetti di blocco) sia più facile da utilizzare o più appropriato per le tue esigenze. ".

http://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html

Non posso effettivamente pensare di situazioni, per applicazioni ad alto livello, in cui l'uso del GCD è obbligatoria e NSOperation potrebbe/non deve essere utilizzato.

Qualche idea?

+0

https: // cocoacast.com/choose-between-nsoperation-and-grand-central-dispatch/ – Masih

risposta

50

Il punto di essere fatta qui è la stessa che Chris Hanson afferma nel suo articolo "When to use NSOperation vs. GCD":

La risposta semplice è una linea guida generale per tutte le applicazioni sviluppo:

Usa sempre il l'astrazione di livello più alto a tua disposizione e rilasciare nelle astrazioni di livello inferiore quando la misurazione mostra che sono necessarie .

In questo caso particolare, significa che durante la scrittura di applicazioni Cocoa , in genere si dovrebbe utilizzare NSOperation anziché utilizzando GCD direttamente. Non a causa di una differenza di efficienza, ma perché NSOperation fornisce un'astrazione di livello superiore in cima ai meccanismi di GCD.

In generale, sono d'accordo con questo.NSOperation e NSOperationQueue forniscono supporto per le dipendenze e una o due altre cose che i blocchi e le code GCD non hanno e sottraggono i dettagli di livello inferiore di come vengono implementate le operazioni simultanee. Se hai bisogno di quella funzionalità, NSOperation è un ottimo modo per andare.

Tuttavia, dopo aver lavorato con entrambi, mi sono trovato a sostituire tutto il mio codice basato su NSOperation con blocchi e code GCD. L'ho fatto per due motivi: c'è un sovraccarico significativo quando si usa NSOperation per azioni frequenti, e credo che il mio codice sia più pulito e più descrittivo quando si usano i blocchi GCD.

La prima ragione viene da profilatura nelle mie applicazioni, dove ho trovato che il processo oggetto di allocazione e deallocazione NSOperation ha preso una notevole quantità di risorse della CPU quando si tratta di piccoli e frequenti azioni, come il rendering di un fotogramma OpenGL ES per lo schermo. GCD blocca completamente l'overhead, portando a significativi miglioramenti delle prestazioni.

Il secondo motivo è più soggettivo, ma credo che il mio codice sia più pulito quando si usano i blocchi di NSOperations. L'acquisizione rapida di scope consentita da un blocco e la natura inline di esse rendono meno codice, perché non è necessario creare sottoclassi NSOperation personalizzate o raggruppare i parametri da passare all'operazione e codice più descrittivo secondo me, perché è possibile inserire il codice da eseguire in una coda nel punto in cui è stato sparato.

Ancora una volta, è una questione di preferenza, ma mi sono trovato a usare GCD di più, anche in applicazioni Cocoa altrimenti più astratte.

+0

NSOperationQueue è ora in grado di utilizzare le chiusure. Questa risposta dovrebbe essere (leggermente) aggiornata? Inoltre, c'è qualche possibilità che NSOperation sia stato ottimizzato negli ultimi 5 anni per ridurre il sovraccarico che hai trovato? –

+0

Devo aggiungere che ho finito per fare esattamente l'opposto: dopo anni di utilizzo diretto di GCD, passare a NSOperationQueue era una boccata d'aria fresca. Il mio comportamento di "accodamento" è ora ben definito e ho il pieno controllo sulle operazioni simultanee massime. Annullare le operazioni in corso e sostituirle con quelle nuove è anche più semplice, con conseguente comportamento ben definito. Uso ancora GCD per semplici operazioni asincrone, ma sono passato a NSOperationQueue per le mie esigenze di accodamento seriale/asincrono. – strangetimes

+0

In aumento per una buona spiegazione. – user3182143

4

Bene, NSOperation non ha equivalenti a dispatch_source_t, dispatch_io, dispatch_data_t, dispatch_semaphore_t, ecc ... È anche un overhead un po 'più alto.

Il rovescio della medaglia, libdispatch non ha equivalenti alle dipendenze operative, alle priorità operative (le priorità delle code sono in qualche modo diverse), o KVO alle operazioni.

+1

'NSOperation' ora è costruito su' GCD', quindi a meno che non ci sia qualcosa in uno di cui hai bisogno, non è nell'altro, non c'è molto a favore rispetto agli altri. – hypercrypt

+1

Richiede ancora assegnazioni di oggetti per operazioni, tra le altre complessità. Per filettature estremamente fini che possono effettivamente rappresentare un sovraccarico significativo. Sì, ho misurato questo; sì, è fondamentale per alcuni dei miei codici. L'involucro di GCD di NSOperation non è affatto la mappatura semplice che ci si potrebbe aspettare, dal momento che ha bisogno di supportare dipendenze, KVO e priorità. –

+0

Ha ragione, ho anche visto un sovraccarico significativo nell'uso di NSOperation per le azioni che si verificano frequentemente, in cui non lo vedo con i blocchi GCD. L'allocazione degli oggetti/la deallocazione può essere molto costosa in questi casi, quindi GCD potrebbe essere più appropriato. –

0

In realtà ho appena letto tutto questo, e sono certo che sarà una sorpresa, le opinioni divergono.

Non riesco a pensare a un caso in cui dovresti utilizzare GCD su NSOperation, ma ciò non significa che un caso del genere non esista. Io, tuttavia, sono d'accordo con un sentimento generale in termini di best practice:

Se si dispone di un paio di strumenti adatti al lavoro (e in questo caso, si ha NSOperation rispetto a un blocco GCD), utilizzare classe con il più alto livello di astrazione (cioè l'API di livello più alto). Non solo è in genere più facile da usare/meno codice, ma otterrai anche dai potenziali miglioramenti futuri introdotti alle API di livello superiore.

13
  • Preferisco GCD cui compito non è molto complessa e prestazioni ottimali della CPU è richiesto.
  • Preferisci NSOperQueue dove l'attività è complessa e richiede annullamento o sospensione di un blocco e gestione delle dipendenze.

GCD è un modo leggero per rappresentare le unità di lavoro che verranno eseguite contemporaneamente. Non pianifichi queste unità di lavoro; il sistema si occupa della pianificazione per te. L'aggiunta di dipendenza tra i blocchi può essere un mal di testa. Annullare o sospendere un blocco crea lavoro extra per te come sviluppatore!

NSOperation e NSOperationQueue aggiungono un sovraccarico extra rispetto a GCD, ma è possibile aggiungere dipendenza tra varie operazioni. È possibile riutilizzare, annullare o sospendere le operazioni. NSOperation è compatibile con Key-Value Observation (KVO); ad esempio, è possibile avviare l'esecuzione di NSOper ascoltando NSNotificationCenter.

Per una spiegazione dettagliata, fare riferimento a questa domanda: NSOperation vs Grand Central Dispatch

1

Ci sono due cose che NSOperationQueue può fare che GCD non fa: Quello minore è dipendenze (aggiungere un operazione a una coda, ma dire che solo l'esecuzione quando alcune altre operazioni sono terminate) e il più grande è che NSOperation ti fornisce un oggetto che può ricevere messaggi mentre il task è in esecuzione, diversamente da GCD che ha blocchi che non possono ricevere messaggi se non in un modo molto limitato. O hai bisogno di queste due funzionalità o non lo fai. Se non lo fai, usare GCD è semplicemente molto più facile da usare.

Ecco perché esempi utili di NSOperation sono sempre piuttosto complessi. Se fossero facili, useresti invece GCD. Di solito crei una sottoclasse di NSOperation, che sarà una quantità significativa di lavoro, o usarne una creata da qualcun altro.

Problemi correlati