NSOperation 및 그랜드 센트럴 디스패치


465

iOS의 동시 프로그래밍에 대해 배우고 있습니다. 지금까지 NSOperation/NSOperationQueue 및 에 대해 읽었습니다 GCD. 이상 을 사용하는 이유는 무엇입니까 ?NSOperationQueueGCD

모두 같은 소리 GCDNSOperationQueue멀리 추상적의 명시적인 생성 NSThreads사용자로부터. 그러나 두 가지 접근 방식의 관계가 명확하지 않으므로 의견을 보내주십시오!


10
좋은 질문에 +1-결과가 궁금합니다. 지금까지 GCD를 CPU 코어로 쉽게 디스패치하여 "새로운 핫 똥"으로 만들 수 있다는 것을 읽었습니다.
까지


답변:


517

GCD작업 기반 동시성 모델을 매우 간단하게 사용할 수있는 저수준 C 기반 API입니다. NSOperation그리고 NSOperationQueue비슷한 일을하는 Objective-C 클래스입니다. NSOperation가 처음 소개되었지만 10.5iOS 2 기준 으로 NSOperationQueue친구는 내부적으로를 사용하여 구현되었습니다 GCD.

일반적으로 요구에 맞는 최고 수준의 추상화를 사용해야합니다. 즉 , 지원하지 않는 작업을 수행해야하는 경우가 아니라면 일반적으로 NSOperationQueue대신 대신 사용해야 합니다 .GCDNSOperationQueue

참고 NSOperationQueue아닌 "무식 다운"GCD의 버전; 사실, NSOperationQueue순수하게 많은 작업을 수행하는 것만으로도 간단하게 할 수있는 일이 많이 있습니다 GCD. (예 :. 한 번에 N 작업을 실행 대역폭이 제한된 큐, 작업 간의 종속성을 설정하는 두 매우 간단한 NSOperation와 매우 어렵다 GCD.) 애플이 가진 아주 좋은 객체 친화적 인 API를 만들 GCD를 활용의 노력을 다 NSOperation. 당신이하지 않는 이유가없는 한 그들의 작업을 활용하십시오.

주의 사항 : 반면에, 실제로 블록을 보내야하고 NSOperationQueue제공 하는 추가 기능이 필요하지 않은 경우 GCD 사용에 아무런 문제가 없습니다. 작업에 적합한 도구인지 확인하십시오.


1
NSOperation은 추상 클래스입니다.
Roshan

3
@Sandy 실제로는 반대입니다. GCD는 NSOperation에서 사용됩니다 (최소한 iOS 및 OS X 버전에서는).
garrettmoon

1
@BJ Homer 시리얼 디스패치 큐에 태스크를 추가하여 디피 던시를 달성 할 수 있습니다. 그래서 justfy 작업은 그 이상의 장점을 가지고 큐 방법
라즈 Aggrawal

3
@RajAggrawal 그렇습니다. 작동하지만 시리얼 큐에 갇혀 있습니다. NSOperation은 "다른 세 가지 작업이 완료된 후에이 작업을 실행하지만 다른 모든 작업과 동시에 실행할 수 있습니다." 다른 큐에서 작업간에 작업 종속성이 존재할 수도 있습니다. 대부분의 사람들은 그럴 필요는 없지만, 그렇게하면 NSOperation이 더 나은 선택이 될 것입니다.
BJ 호머

369

와 라인에서 관련 질문에 대한 내 대답은 , 나는 후자는 GCD하지 않는 것을해야 할 일을 제공하지 않는 한, BJ에 동의하고 당신에게 NSOperation / NSOperationQueue 이상 GCD 처음 모습을 제안하겠습니다.

GCD 이전에는 동시성 관리를 위해 응용 프로그램 내에서 많은 NSOperations / NSOperationQueues를 사용했습니다. 그러나 정기적으로 GCD를 사용하기 시작한 이래로 NSOperations와 NSOperationQueues를 블록 및 디스패치 큐로 거의 완전히 대체했습니다. 이것은 실제로 두 기술을 실제로 사용한 방법과 내가 수행 한 프로파일 링에서 비롯된 것입니다.

첫째, NSOperations 및 NSOperationQueues를 사용할 때 사소한 양의 오버 헤드가 있습니다. 이들은 Cocoa 객체이며 할당 및 할당 해제가 필요합니다. 필자가 작성한 60 FPS에서 3D 장면을 렌더링하는 iOS 응용 프로그램에서 NSOperations를 사용하여 렌더링 된 각 프레임을 캡슐화했습니다. 필자가이 프로파일을 작성할 때 이러한 NSOperation의 생성 및 해제는 실행중인 응용 프로그램의 CPU주기 중 상당 부분을 차지했으며 속도가 느려졌습니다. 나는 이것을 간단한 블록과 GCD 시리얼 큐로 교체했고, 오버 헤드가 사라져서 렌더링 성능이 눈에 띄게 향상되었습니다. NSOperations 사용으로 인한 오버 헤드를 발견 한 유일한 곳은 아니 었으며 Mac과 iOS 모두에서이 기능을 보았습니다.

둘째, NSOperations를 사용할 때 일치하기 어려운 블록 기반 디스패치 코드의 우아함이 있습니다. 블록에 몇 줄의 코드를 래핑하고 직렬 또는 동시 큐에서 수행되도록 디스패치하는 것이 매우 편리합니다.이 작업을 수행하려면 사용자 지정 NSOperation 또는 NSInvocationOperation을 생성하면 훨씬 더 많은 지원 코드가 필요합니다. NSBlockOperation을 사용할 수 있다는 것을 알고 있지만 GCD에 무언가를 전달할 수도 있습니다. 이 코드를 응용 프로그램의 관련 처리와 함께 인라인으로 감싸면 이러한 작업을 캡슐화하는 별도의 방법이나 사용자 지정 NSOperation보다 코드 구성이 향상됩니다.

NSOperations 및 NSOperationQueues는 여전히 매우 유용합니다. GCD는 NSOperationQueues가 매우 복잡한 종속성 그래프를 설정할 수있는 실제 종속성 개념이 없습니다. 소수의 경우 NSOperationQueues를 사용합니다.

전반적으로 필자는 일반적으로 작업을 수행하는 최고 수준의 추상화 사용을 옹호하지만 GCD의 하위 수준 API를 주장하는 경우입니다. 내가 이야기 한 iOS 및 Mac 개발자들 중 대다수는 지원하지 않는 OS 버전 (iOS 4.0 및 Snow Leopard 이전)을 대상으로하지 않는 한 NSOperations를 통해 GCD를 사용하기로 결정했습니다.


20
나는 단지 약간 동의하지 않는다. 나는 평범한 GCD를 꽤 많이 사용합니다. 그러나이 답변에서 NSBlockOperation을 너무 많이 할인한다고 생각합니다. NSOperationQueue의 모든 이점 (종속성, 디버깅 가능성 등)도 차단 작업에 적용됩니다.
BJ 호머

4
@ BJHomer-NSBlockOperation을 피하는 것이 개인적인 경우보다 개인적인 취향의 문제라고 생각합니다.하지만 사용으로 인한 오버 헤드를 확인한 후 NSOperations에서 멀어지면 몇 가지 응용 프로그램이 다운됩니다. 블록을 사용하려는 경우 종속성 지원이 필요한 경우를 제외하고는 GCD에 올인하는 경향이 있습니다.
Brad Larson

1
+1,이 분석에 감사드립니다. Apple은 WWDC 2012의 동시 UI 세션과 같이 두 가지를 모두 옹호하는 것으로 보입니다.
orip

1
@VolureDarkAngel-GCD는 이와 같은 디스패치를 ​​처리하는 데 매우 빠릅니다. 느린 I / O 액세스 또는 일종의 무언가로 인해 대기열에 업데이트 더미를 백업하지 않는 한 설명과 같은 상황에서 병목 현상이 발생하지 않아야합니다. 그러나 아마도 여기서는 그렇지 않습니다.
Brad Larson

1
@ asma22-청크 단위로 수행 할 수있는 계산이 일반적이지만 한 단계의 최종 계산에는 여러 이전 단계의 결과가 필요할 수 있습니다. 이 경우 이후 작업이 이전 작업에 종속되도록하고 마지막 작업이 실행되기 전에 모든 작업이 완료되도록 일정을 관리합니다.
Brad Larson

101

GCD저수준 C 기반 API입니다.
NSOperationNSOperationQueue목표 - C 클래스입니다.
NSOperationQueue객관적인 C 래퍼 GCD입니다. NSOperation을 사용하는 경우 그랜드 센트럴 디스패치를 암시 적으로 사용 합니다.

NSOperation에 비해 GCD의 장점 :
i. 구현
에 대한 GCD구현은 매우 가벼운 무게가
NSOperationQueue복잡하고 중량이 무거운

GCD에 비해 NSOperation의 장점 :

나는. Control On Operation
은 일시 정지, 취소, 재개를 할 수 있습니다NSOperation

ii. 종속성
이 둘 사이에 종속성을 설정할 수 있습니다 NSOperations
모든 종속성이 완성에 대해 true를 반환 할 때까지 작업이 시작되지 않습니다.

iii. 작업
상태는 작업 또는 작업 큐의 상태를 모니터링 할 수 있습니다. 준비, 실행 또는 완료

iv. 최대
작업 수 동시에 실행할 수있는 최대 대기 작업 수를 지정할 수 있습니다.

시에로 이동 GCD또는NSOperation
당신이 (모든 위에서 언급 한) 사용을 큐보다 효율적으로 관리를 원하는 NSOperation 당신이 오버 헤드가 적은 원하는 간단한 경우에 (그냥 약간의 추가 작업으로 "배경으로"몇 가지 작업을 수행 할) 사용GCD

심판 :
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/


이미 말한 것처럼 NSOperationQueue에서 최대 작업 수를 지정할 수 있습니다. 그러면 GCD에서 최대 작업 수 (디스패치 큐)는 무엇입니까? 프로젝트가 있다고 가정하면 얼마나 많은 작업 (디스패치 큐)을 할 수 있습니까? 또는 우리가 할 수있는 최대 한도입니다.
Roshan Sah

자세한 내용은 시스템 상태에 따라 다릅니다. stackoverflow.com/questions/14995801/…
Sangram Shivankar

DispatchWorkItem을 사용하여 GCD에서도 작업을 취소 할 수 있으며 일시 중단 및 재개도 가능합니다
Ankit garg

@Ankitgarg DispatchWorkItem에서 cancel을 호출하면 작업이 아직 실행되지 않은 경우 작업 실행이 중지되지만 이미 실행중인 작업은 중단되지 않습니다. 어떻게 DispatchWorkItem을 일시 중지 / 다시 시작합니까 ??
abhimuralidharan

34

GCD보다 NSOperation을 선호하는 또 다른 이유는 NSOperation의 취소 메커니즘입니다. 예를 들어, 수십 장의 사진을 보여주는 500px와 같은 앱은 NSOperation을 사용하여 테이블보기 또는 컬렉션보기를 스크롤 할 때 보이지 않는 이미지 셀의 요청을 취소 할 수 있습니다. 이는 앱 성능을 크게 향상시키고 메모리 공간을 줄일 수 있습니다. GCD는 이것을 쉽게 지원할 수 없습니다.

또한 NSOperation을 통해 KVO가 가능합니다.

다음 은 읽을 가치가있는 Eschaton의 기사입니다.


4
그것은 당신이 취소되는 것은 이미지를로드의 네트워크 작업 인 경우에, 당신이 필요로하지 않는 것이 주목할 가치가있다 NSOperation,이에 대한 NSURLSessionTask.cancel그리고 NSURLSession.invalidateAndCancel이 기능을 제공합니다. 일반적 NSURLSession의 기능의 일부를 제공하는 NSOperationQueue것처럼, NSURLSessionTask의 일부 기능 제공NSOperation
해조

@algal 여기에 설명 된대로 ( stackoverflow.com/questions/21918722/… ) NSURLSession은 NSOperationQueue를 빌딩 블록으로 사용하는 것으로 보입니다.
kalan nawarathne

33

GCD는 실제로 NSOperationQueue보다 낮은 수준이며, 주요 이점은 구현이 매우 가볍고 잠금없는 알고리즘 및 성능에 중점을 둔다는 것입니다.

NSOperationQueue는 GCD에서 사용할 수없는 기능을 제공하지만 그다지 비용이 들지 않으며 NSOperationQueue의 구현은 복잡하고 무겁고 많은 잠금이 필요하며 내부적으로 최소한의 방식으로 GCD를 사용합니다.

NSOperationQueue가 제공하는 기능이 꼭 필요하다면 GCD로 충분하다면 성능을 높이고 CPU 및 전력 비용을 크게 낮추고 유연성을 높이기 위해 직접 사용하는 것이 좋습니다.


24

NSQueueOperations와 GCD는 UI Application Main Tread를 해제하여 별도의 스레드에서 백그라운드에서 무거운 계산 작업을 실행할 수 있습니다.

이전 게시물을 기반으로 NSOperations에 addDependency가 있으므로 작업을 순차적으로 대기열에 넣을 수 있습니다.

그러나 dispatch_queue_create를 사용하여 대기열에서 작업을 실행할 수있는 GCD 직렬 대기열에 대해서도 읽었습니다. 이를 통해 일련의 작업을 순차적으로 실행할 수 있습니다.

GCD에 비해 NSQueueOperation의 장점 :

  1. 의존성을 추가하고 의존성을 제거 할 수 있으므로 하나의 트랜잭션에 대해 종속성을 사용하여 순차적으로 실행할 수 있고 다른 트랜잭션에 대해 동시에 실행할 수 있지만 GCD는이 방법으로 실행할 수 없습니다.

  2. 작업이 대기열에 있으면 작업을 취소하기 쉬우 며 실행 중이면 중지 할 수 있습니다.

  3. 최대 동시 작업 수를 정의 할 수 있습니다.

  4. 대기열에있는 작업을 일시 중단 할 수 있습니다

  5. 대기열에 보류중인 작업 수를 찾을 수 있습니다.


6

GCD는 사용하기 매우 쉽습니다. 백그라운드에서 무언가를하고 싶다면 코드를 작성하고 백그라운드 큐에 전달하면됩니다. NSOperation과 동일한 작업을 수행하는 것은 많은 추가 작업입니다.

NSOperation의 장점은 (a) 메시지를 보낼 수있는 실제 개체가 있고 (b) NSOperation을 취소 할 수 있다는 것입니다. 그것은 사소한 것이 아닙니다. NSOperation을 서브 클래 싱해야합니다. 취소 및 작업을 올바르게 완료하려면 코드를 올바르게 작성해야합니다. 따라서 간단한 것에는 GCD를 사용하고 더 복잡한 것에는 NSOperation의 하위 클래스를 만듭니다. NSInvocationOperation 및 NSBlockOperation 서브 클래스가 있지만 GCD로 수행하는 모든 작업이 더 쉬워 지므로 사용할 이유가 없습니다.


3

NSOperations는 단순히 Grand Central Dispatch 위에 구축 된 API입니다. 따라서 NSOperations를 사용할 때 여전히 Grand Central Dispatch를 사용하고 있습니다. 단지 NSOperations가 여러분이 좋아할만한 멋진 기능을 제공한다는 것입니다. 일부 작업을 다른 작업에 종속시키고 항목을 합산 한 후 대기열을 다시 정렬하는 등의 작업을 수행 할 수 있습니다. 실제로 ImageGrabber는 이미 NSOperations 및 작업 대기열을 사용하고 있습니다! ASIHTTPRequest는 후드 아래에서이를 사용하며 원하는 경우 다른 동작에 사용하는 작업 대기열을 구성 할 수 있습니다. 어느 것을 사용해야합니까? 앱에 적합한 것이 있습니다. 이 응용 프로그램의 경우 매우 간단하므로 NSOperation의 멋진 기능이 필요하지 않은 Grand Central Dispatch를 직접 사용했습니다. 그러나 앱에 필요한 경우 자유롭게 사용하십시오!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.