Uczę się o programowaniu współbieżnym na iOS. Do tej pory czytałem o NSOperation
/NSOperationQueue
i GCD
. Jakie są powody używania NSOperationQueue
over GCD
i vice versa?
Brzmi jak oba GCD
i NSOperationQueue
oddziela jawne tworzenie NSThreads
od użytkownika. Jednak związek między tymi dwoma podejściami nie jest dla mnie jasny, więc wszelkie uwagi należy docenić!
ios
concurrency
grand-central-dispatch
nsoperation
nsoperationqueue
Niedziela poniedziałek
źródło
źródło
Odpowiedzi:
GCD
to niskopoziomowy interfejs API oparty na języku C, który umożliwia bardzo proste korzystanie z modelu współbieżności opartego na zadaniach.NSOperation
iNSOperationQueue
są klasami Objective-C, które robią podobne rzeczy.NSOperation
został wprowadzony jako pierwszy, ale od wersji 10.5 i iOS 2 ,NSOperationQueue
a znajomi są wdrażani wewnętrznie za pomocąGCD
.Ogólnie powinieneś używać najwyższego poziomu abstrakcji, który odpowiada Twoim potrzebom. Oznacza to, że zwykle powinieneś używać
NSOperationQueue
zamiastGCD
, chyba że musisz zrobić coś,NSOperationQueue
co nie obsługuje.Zauważ, że
NSOperationQueue
nie jest to „głupia” wersja GCD; w rzeczywistości istnieje wiele rzeczy, które możesz zrobić w bardzo prosty sposób,NSOperationQueue
które wymagają dużo pracy z czystymGCD
. (Przykłady: kolejki o ograniczonej przepustowości, które uruchamiają tylko operacje N na raz; ustalanie zależności między operacjami. Obie są bardzo prosteNSOperation
, bardzo trudne zGCD
.) Apple ciężko pracowało nad wykorzystaniem GCD do stworzenia bardzo ładnego, przyjaznego obiektowo interfejsu APINSOperation
. Skorzystaj z ich pracy, chyba że masz powód, aby tego nie robić.Zastrzeżenie : Z drugiej strony, jeśli naprawdę musisz po prostu wysłać blok i nie potrzebujesz żadnej dodatkowej funkcjonalności, która
NSOperationQueue
zapewnia, nie ma nic złego w korzystaniu z GCD. Tylko upewnij się, że jest to odpowiednie narzędzie do pracy.źródło
Zgodnie z moją odpowiedzią na powiązane pytanie zamierzam się nie zgodzić z BJ i zasugerować, aby najpierw spojrzeć na GCD przez NSOperation / NSOperationQueue, chyba że to drugie zapewnia coś, czego GCD nie potrzebuje.
Przed GCD korzystałem z wielu aplikacji NSOperations / NSOperationQueues w swoich aplikacjach do zarządzania współbieżnością. Jednak odkąd zacząłem używać GCD regularnie, prawie całkowicie zastąpiłem NSOperations i NSOperationQueues blokami i kolejkami wysyłki. Wynika to z tego, jak korzystałem z obu technologii w praktyce oraz z profilowania, które na nich przeprowadziłem.
Po pierwsze, korzystanie z NSOperations i NSOperationQueues wiąże się z nietrywialnym obciążeniem. Są to obiekty kakaowe i należy je przydzielić i zwolnić. W napisanej przeze mnie aplikacji na iOS, która renderuje trójwymiarową scenę przy 60 FPS, używałem NSOperations do enkapsulacji każdej renderowanej ramki. Kiedy profilowałem to, tworzenie i porzucanie tych NSOperations odpowiadało za znaczną część cykli procesora w uruchomionej aplikacji i spowalniało rzeczy. Zastąpiłem je prostymi blokami i kolejką szeregową GCD, a ten narzut zniknął, co prowadzi do zauważalnie lepszej wydajności renderowania. To nie było jedyne miejsce, w którym zauważyłem narzut dzięki korzystaniu z NSOperations i widziałem to zarówno na Macu, jak i iOS.
Po drugie, blokowy kod wysyłki ma elegancję, którą trudno dopasować przy użyciu NSOperations. Bardzo wygodne jest zawinięcie kilku wierszy kodu w blok i wysłanie go do wykonania w kolejce szeregowej lub współbieżnej, gdzie utworzenie niestandardowego NSOperation lub NSInvocationOperation wymaga o wiele więcej kodu pomocniczego. Wiem, że możesz użyć NSBlockOperation, ale równie dobrze możesz wtedy wysłać coś do GCD. Zawijanie tego kodu w bloki w powiązaniu z powiązanym przetwarzaniem w twojej aplikacji prowadzi moim zdaniem do lepszej organizacji kodu niż posiadanie osobnych metod lub niestandardowych NSOperations, które zawierają te zadania.
NSOperations i NSOperationQueues nadal mają bardzo dobre zastosowania. GCD nie ma prawdziwej koncepcji zależności, w której NSOperationQueues może skonfigurować dość złożone wykresy zależności. Używam do tego NSOperationQueues w kilku przypadkach.
Ogólnie rzecz biorąc, chociaż zwykle opowiadam się za wykorzystaniem najwyższego poziomu abstrakcji, który spełnia zadanie, jest to jeden przypadek, w którym opowiadam się za niższym poziomem API GCD. Spośród programistów iOS i Mac, z którymi rozmawiałem na ten temat, zdecydowana większość decyduje się na użycie GCD zamiast NSOperations, chyba że są ukierunkowane na wersje systemu operacyjnego bez obsługi tego systemu (te wcześniejsze niż iOS 4.0 i Snow Leopard).
źródło
GCD
jest niskopoziomowym interfejsem API opartym na C.NSOperation
iNSOperationQueue
są klasami Objective-C.NSOperationQueue
obiektywne C owijkaGCD
. Jeśli używasz NSOperation, to domyślnie używasz Grand Central Dispatch.Przewaga GCD nad NSOperation:
i. Realizacja
Dla
GCD
realizacji jest bardzo lekkiNSOperationQueue
jest złożony i heavy-weightZalety NSOperation w porównaniu z GCD:
ja. Kontroluj działanie
można wstrzymać, anulować, wznowić
NSOperation
ii. Zależności,
które można ustawić, zależność między dwiema
NSOperations
operacjami nie rozpocznie się, dopóki wszystkie jej zależności nie zwrócą wartości true dla zakończenia.
iii. Stan operacji
może monitorować stan operacji lub kolejki operacji. gotowe, wykonane lub zakończone
iv. Maksymalna liczba operacji
Można określić maksymalną liczbę operacji w kolejce, które mogą być uruchomione jednocześnie
Kiedy iść
GCD
lubNSOperation
kiedy chcesz mieć większą kontrolę nad kolejką (wszystkie wyżej wymienione),
NSOperation
a także w prostych przypadkach, w których chcesz zmniejszyć obciążenie (po prostu chcesz wykonać trochę pracy „w tle” przy bardzo małej dodatkowej pracy)GCD
ref:
https://cocoacasts.com/choosing-between-nsoperation-and-grand-central-dispatch/ http://iosinfopot.blogspot.in/2015/08/nsthread-vs-gcd-vs-nsoperationqueue.html http : //nshipster.com/nsoperation/
źródło
Innym powodem preferowania NSOperation nad GCD jest mechanizm anulowania NSOperation. Na przykład aplikacja taka jak 500px, która pokazuje dziesiątki zdjęć, używając NSOperation możemy anulować żądania niewidocznych komórek obrazu, gdy przewijamy widok tabeli lub widok kolekcji, może to znacznie poprawić wydajność aplikacji i zmniejszyć zużycie pamięci. GCD nie może tego łatwo obsłużyć.
Również dzięki NSOperation KVO może być możliwe.
Oto artykuł z Eschaton, który warto przeczytać.
źródło
NSOperation
do tego, jakNSURLSessionTask.cancel
iNSURLSession.invalidateAndCancel
zapewnienia tej funkcji. Na ogół,NSURLSession
stanowi część funkcjonalnośćNSOperationQueue
, coNSURLSessionTask
stanowi część funkcjonalnośćNSOperation
GCD jest rzeczywiście na niższym poziomie niż NSOperationQueue, jego główną zaletą jest to, że jego implementacja jest bardzo lekka i skupia się na algorytmach bez blokady i wydajności.
NSOperationQueue zapewnia funkcje, które nie są dostępne w GCD, ale wiążą się one z niebanalnymi kosztami, wdrożenie NSOperationQueue jest złożone i ciężkie, wymaga dużej ilości blokowania i używa GCD wewnętrznie tylko w bardzo minimalny sposób.
Jeśli potrzebujesz udogodnień zapewnianych przez NSOperationQueue, skorzystaj z niego, ale jeśli GCD jest wystarczający dla twoich potrzeb, zaleciłbym użycie go bezpośrednio dla lepszej wydajności, znacznie niższego kosztu procesora i energii oraz większej elastyczności.
źródło
Zarówno NSQueueOperations, jak i GCD umożliwiają wykonywanie ciężkich zadań obliczeniowych w tle na osobnych wątkach poprzez zwolnienie głównego profilu aplikacji interfejsu użytkownika.
Cóż, w oparciu o poprzedni post widzimy, że NSOperations ma addDependency, dzięki czemu możesz kolejkować swoje operacje jedna po drugiej.
Ale czytam również o kolejkach szeregowych GCD, które możesz utworzyć, uruchamiaj swoje operacje w kolejce za pomocą dispatch_queue_create. Umożliwi to uruchamianie zestawu operacji jeden po drugim w sekwencyjny sposób.
Zalety NSQueueOperation w porównaniu z GCD:
Pozwala na dodanie zależności i pozwala na usunięcie zależności, więc dla jednej transakcji można uruchomić sekwencyjnie przy użyciu zależności, a dla drugiej transakcji jednocześnie, podczas gdy GCD nie pozwala na uruchomienie w ten sposób.
Można łatwo anulować operację, jeśli znajduje się ona w kolejce, można ją zatrzymać, jeśli jest uruchomiona.
Możesz zdefiniować maksymalną liczbę jednoczesnych operacji.
Możesz zawiesić operacje, które znajdują się w kolejce
Możesz sprawdzić, ile jest oczekujących operacji w kolejce.
źródło
GCD jest bardzo łatwy w użyciu - jeśli chcesz zrobić coś w tle, wszystko, co musisz zrobić, to napisać kod i wysłać go w kolejce w tle. Robienie tego samego z NSOperation to dużo dodatkowej pracy.
Zaletą NSOperation jest to, że (a) masz prawdziwy obiekt, do którego możesz wysyłać wiadomości, oraz (b) możesz anulować NSOperation. To nie jest trywialne. Musisz podklasować NSOperation, musisz poprawnie napisać kod, aby anulowanie i prawidłowe zakończenie zadania działały poprawnie. Więc dla prostych rzeczy używasz GCD, a dla bardziej skomplikowanych rzeczy tworzysz podklasę NSOperation. (Istnieją podklasy NSInvocationOperation i NSBlockOperation, ale wszystko, co robią, jest łatwiejsze do zrobienia dzięki GCD, więc nie ma dobrego powodu, aby z nich korzystać).
źródło
Cóż, NSOperations to po prostu interfejs API zbudowany na bazie Grand Central Dispatch. Więc kiedy używasz NSOperations, naprawdę nadal używasz Grand Central Dispatch. Po prostu NSOperations daje ci kilka fantazyjnych funkcji, które mogą ci się spodobać. Możesz uzależnić niektóre operacje od innych, zmienić kolejkę po sumbitowaniu przedmiotów i inne podobne rzeczy. W rzeczywistości ImageGrabber już używa NSOperations i kolejek operacyjnych! ASIHTTPRequest używa ich pod maską, a jeśli chcesz, możesz skonfigurować kolejkę operacji, której używa, dla różnych zachowań. Którego powinieneś użyć? Cokolwiek ma sens dla Twojej aplikacji. W przypadku tej aplikacji jest to dość proste, więc użyliśmy bezpośrednio Grand Central Dispatch, bez potrzeby fantazyjnych funkcji NSOperation. Ale jeśli potrzebujesz ich do swojej aplikacji, skorzystaj z niej!
źródło