NSOperation vs Grand Central Dispatch

Ik leer over gelijktijdig programmeren voor iOS. Tot nu toe heb ik gelezen over NSOperation/NSOperationQueueen GCD. Wat zijn de redenen om NSOperationQueuete gebruiken in plaats van GCDen vice versa?

Klinkt als zowel GCDals NSOperationQueueabstraheren de expliciete aanmaak van NSThreadsvan de gebruiker. De relatie tussen de twee benaderingen is mij echter niet duidelijk, dus alle feedback wordt op prijs gesteld!


Antwoord 1, autoriteit 100%

GCDis een low-level C-gebaseerde API die zeer eenvoudig gebruik van een taakgebaseerd gelijktijdigheidsmodel mogelijk maakt. NSOperationen NSOperationQueuezijn Objective-C-klassen die hetzelfde doen. NSOperationwerd eerst geïntroduceerd, maar vanaf 10.5en iOS 2, NSOperationQueueen vrienden worden intern geïmplementeerd met behulp van GCD.

Over het algemeen moet u het hoogste abstractieniveau gebruiken dat bij uw behoeften past. Dit betekent dat u gewoonlijk NSOperationQueuemoet gebruiken in plaats van GCD, tenzij u iets moet doen dat NSOperationQueueniet ondersteunt.

Merk op dat NSOperationQueuegeen “gedimde” versie van GCD is; in feite zijn er veel dingen die je heel eenvoudig kunt doen met NSOperationQueuedie veel werk vergen met pure GCD. (Voorbeelden: wachtrijen met beperkte bandbreedte die slechts N bewerkingen tegelijk uitvoeren; afhankelijkheden tussen bewerkingen vaststellen. Beide erg eenvoudig met NSOperation, erg moeilijk met GCD.) Apple heeft het gedaan hard werken om GCD te gebruiken om een ​​zeer mooie objectvriendelijke API te maken met NSOperation. Profiteer van hun werk, tenzij je een reden hebt om dat niet te doen.

Voorbehoud:
Aan de andere kant, als je echt alleen maar een blokkering moet verzenden en geen van de extra functionaliteit nodig hebt die NSOperationQueuebiedt, is er niets mis met het gebruik van GCD. Zorg ervoor dat dit het juiste gereedschap is voor de klus.


Antwoord 2, autoriteit 71%

In lijn met mijn antwoord op een gerelateerde vraag, ben ik het niet eens met BJ en stel voor dat je eerst kijkt bij GCD over NSOperation / NSOperationQueue, tenzij de laatste iets biedt dat u nodig heeft dat GCD niet heeft.

Vóór GCD gebruikte ik veel NSOperations / NSOperationQueues in mijn applicaties voor het beheren van gelijktijdigheid. Sinds ik GCD echter regelmatig ben gaan gebruiken, heb ik NSOperations en NSOperationQueues bijna volledig vervangen door blokken en verzendwachtrijen. Dit komt door de manier waarop ik beide technologieën in de praktijk heb gebruikt en door de profilering die ik erop heb uitgevoerd.

Ten eerste is er een niet-triviale hoeveelheid overhead bij het gebruik van NSOperations en NSOperationQueues. Dit zijn Cocoa-objecten en ze moeten worden toegewezen en ongedaan worden gemaakt. In een iOS-toepassing die ik heb geschreven en die een 3D-scène met 60 FPS weergeeft, gebruikte ik NSOperations om elk weergegeven frame in te kapselen. Toen ik dit profileerde, was het maken en afbreken van deze NSOperations verantwoordelijk voor een aanzienlijk deel van de CPU-cycli in de draaiende applicatie, en dit vertraagde de zaken. Ik verving deze door eenvoudige blokken en een seriële GCD-wachtrij, en die overhead verdween, wat leidde tot merkbaar betere weergaveprestaties. Dit was niet de enige plek waar ik overhead opmerkte bij het gebruik van NSOperations, en ik heb dit zowel op Mac als op iOS gezien.

Ten tweede is er een elegantie aan op blokken gebaseerde verzendcode die moeilijk te evenaren is bij het gebruik van NSOperations. Het is zo ongelooflijk handig om een ​​paar regels code in een blok te wikkelen en het te verzenden om te worden uitgevoerd op een seriële of gelijktijdige wachtrij, waar het maken van een aangepaste NSOperation of NSInvocationOperation om dit te doen veel meer ondersteunende code vereist. Ik weet dat je een NSBlockOperation kunt gebruiken, maar dan kun je net zo goed iets naar GCD sturen. Het inpakken van deze code in blokken in lijn met gerelateerde verwerking in uw toepassing leidt naar mijn mening tot een betere code-organisatie dan het hebben van afzonderlijke methoden of aangepaste NSO-bewerkingen die deze taken inkapselen.

NSOperations en NSOperationQueues hebben nog steeds zeer goede toepassingen. GCD heeft geen echt concept van afhankelijkheden, waar NSOperationQueues behoorlijk complexe afhankelijkheidsgrafieken kan opzetten. Ik gebruik hiervoor in een handvol gevallen NSOperationQueues.

Hoewel ik gewoonlijk pleit voor het gebruik van het hoogste abstractieniveau waarmee de taak kan worden uitgevoerd, pleit ik in het algemeen voor de lagere API van GCD. Van de iOS- en Mac-ontwikkelaars met wie ik hierover heb gesproken, kiest de overgrote meerderheid ervoor om GCD te gebruiken via NSOperations, tenzij ze zich richten op OS-versies zonder ondersteuning daarvoor (die vóór iOS 4.0 en Snow Leopard).


Antwoord 3, autoriteit 23%

GCDis een low-level C-gebaseerde API.
NSOperationen NSOperationQueuezijn Objective-C-klassen.
NSOperationQueueis objectieve C-wrapper over GCD.
Als u NSOperation gebruikt, gebruikt u impliciet Grand Central Dispatch.

GCD-voordeel ten opzichte van NSOperation:
ik. implementatie
Voor GCDis de implementatie erg licht
NSOperationQueueis complex en zwaar

NSOperation-voordelen ten opzichte van GCD:

i. Bediening bij bediening
u kunt een NSOperation

onderbreken, annuleren en hervatten

ii. Afhankelijkheden
u kunt een afhankelijkheid instellen tussen twee NSOperations
bewerking wordt pas gestart als al zijn afhankelijkheden waar terugkeren voor voltooid.

iii. Staat van operatie
kan de status van een bewerking of bewerkingswachtrij bewaken.
klaar, uitvoeren of klaar

iv. Max aantal bewerkingen
u kunt het maximale aantal bewerkingen in de wachtrij specificeren dat tegelijkertijd kan worden uitgevoerd

Wanneer kiezen voor GCDof NSOperation
als je meer controle wilt over de wachtrij (alle hierboven genoemde), gebruik dan NSOperation
en voor eenvoudige gevallen waarin u minder overhead wilt
(je wilt gewoon wat werk “naar de achtergrond” doen met heel weinig extra werk) gebruik GCD

ref:
https://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch /
http://iosinfopot.blogspot.in/2015/08/nsthread-vs- ggd-vs-nsoperationqueue.html
http://nshipster.com/nsoperation/


Antwoord 4, autoriteit 6%

Een andere reden om NSOperation te verkiezen boven GCD is het annuleringsmechanisme van NSOperation. Bijvoorbeeld, een app zoals 500px die tientallen foto’s toont, met NSOperation kunnen we verzoeken van onzichtbare afbeeldingscellen annuleren wanneer we door de tabelweergave of collectieweergave scrollen, dit kan de app-prestaties aanzienlijk verbeteren en de geheugenvoetafdruk verminderen. GCD kan dit niet gemakkelijk ondersteunen.

Ook met NSOperation kan KVO mogelijk zijn.

Hieris een artikel van Eschaton dat het lezen waard is.


Antwoord 5, autoriteit 6%

GCD is inderdaad van een lager niveau dan NSOperationQueue, het grote voordeel is dat de implementatie erg licht is en gericht is op lock-free algoritmen en prestaties.

NSOperationQueue biedt faciliteiten die niet beschikbaar zijn in GCD, maar ze brengen niet-triviale kosten met zich mee, de implementatie van NSOperationQueue is complex en zwaar, brengt veel vergrendeling met zich mee en gebruikt GCD intern slechts op een zeer minimale manier .

Als je de faciliteiten van NSOperationQueue nodig hebt, gebruik het dan, maar als GCD voldoende is voor je behoeften, raad ik aan het rechtstreeks te gebruiken voor betere prestaties, aanzienlijk lagere CPU- en stroomkosten en meer flexibiliteit.


Antwoord 6, autoriteit 4%

Zowel NSQueueOperations als GCD maken het mogelijk om zware rekentaken op de achtergrond op afzonderlijke threads uit te voeren door het hoofdprofiel van de UI-toepassing vrij te maken.

Nou, op basis van eerdere berichten zien we dat NSOperations addDependency heeft, zodat u uw bewerkingen achter elkaar in de wachtrij kunt plaatsen.

Maar ik heb ook gelezen over seriële GCD-wachtrijen die u kunt maken om uw bewerkingen in de wachtrij uit te voeren met behulp van dispatch_queue_create. Dit maakt het mogelijk om een ​​reeks bewerkingen achter elkaar uit te voeren op een sequentiële manier.

NSQueueOperation-voordelen ten opzichte van GCD:

  1. Hiermee kunt u afhankelijkheid toevoegen en kunt u afhankelijkheid verwijderen, zodat u voor één transactie sequentieel kunt uitvoeren met afhankelijkheid en voor andere transacties tegelijkertijd terwijl GCD
    staat niet toe om op deze manier te werken.

  2. Het is gemakkelijk om een ​​bewerking te annuleren als deze in de wachtrij staat en kan worden gestopt als deze wordt uitgevoerd.

  3. U kunt het maximum aantal gelijktijdige bewerkingen definiëren.

  4. U kunt de bewerking die in de wachtrij staat onderbreken

  5. U kunt zien hoeveel bewerkingen in behandeling er in de wachtrij staan.


Antwoord 7

GCD is heel gemakkelijk te gebruiken – als u iets op de achtergrond wilt doen, hoeft u alleen maar de code te schrijven en deze in een wachtrij op de achtergrond te plaatsen. Hetzelfde doen met NSOperation is veel extra werk.

Het voordeel van NSOperation is dat (a) u een echt object heeft waarnaar u berichten kunt sturen, en (b) dat u een NSOperation kunt annuleren. Dat is niet triviaal. U moet NSOperation onderklassen, u moet uw code correct schrijven, zodat zowel het annuleren als het correct voltooien van een taak correct werken. Dus voor simpele dingen gebruik je GCD, en voor meer gecompliceerde dingen maak je een subklasse van NSOperation aan. (Er zijn subklassen NSInvocationOperation en NSBlockOperation, maar alles wat ze doen is gemakkelijker gedaan met GCD, dus er is geen goede reden om ze te gebruiken).


Antwoord 8

Nou, NSOperations is gewoon een API die bovenop Grand Central Dispatch is gebouwd. Dus als je NSOperations gebruikt, gebruik je eigenlijk nog steeds Grand Central Dispatch.
Het is gewoon dat NSOperations je een aantal mooie functies geeft die je misschien leuk vindt. U kunt sommige bewerkingen afhankelijk maken van andere bewerkingen, wachtrijen opnieuw ordenen nadat u items hebt toegevoegd, en dergelijke.
ImageGrabber maakt zelfs al gebruik van NSOperations en bewerkingswachtrijen! ASIHTTPRequest gebruikt ze onder de motorkap en u kunt de bewerkingswachtrij configureren die het gebruikt voor ander gedrag als u dat wilt.
Dus welke moet je gebruiken? Wat ook maar logisch is voor uw app. Voor deze app is het vrij eenvoudig, dus we hebben Grand Central Dispatch gewoon rechtstreeks gebruikt, geen behoefte aan de mooie functies van NSOperation. Maar als je ze nodig hebt voor je app, gebruik ze dan gerust!


Antwoord 9

Ik ben het eens met @Sangram en andere antwoorden, maar wil enkele punten toevoegen. Corrigeer me als ik het mis heb.

Ik denk dat de eerste twee punten van @Sangram’s antwoord nu niet geldig zijn (i. Controle op bewerking ii. Afhankelijkheden). We kunnen deze twee bereiken door ook GCD te gebruiken. Proberen uit te leggen door middel van code (focus niet op de kwaliteit van de code, dit is alleen ter referentie)

func methodsOfGCD() {
    let concurrentQueue = DispatchQueue.init(label: "MyQueue", qos: .background, attributes: .concurrent)
    //We can suspend and resume Like this
    concurrentQueue.suspend()
    concurrentQueue.resume()
    //We can cancel using DispatchWorkItem
    let workItem = DispatchWorkItem {
        print("Do something")
    }
    concurrentQueue.async(execute: workItem)
    workItem.cancel()
    //Cam add dependency like this.
    //Operation 1
    concurrentQueue.async(flags: .barrier) {
        print("Operation1")
    }
    //Operation 2
    concurrentQueue.async(flags: .barrier) {
        print("Operation2")
    }
    //Operation 3.
    //Operation 3 have dependency on Operation1 and Operation2. Once 1 and 2 will finish will execute Operation 3. Here operation queue work as a serial queue.
    concurrentQueue.async(flags: .barrier) {
        print("Operation3")
    }
}

Other episodes