Grand Central Dispatch

GCD?

Grand Central Dispatch(이하 GCD)는 동시성 운영을 관리하기 위한 Apple의 로우 레벨 API 이다. GCD는 스레드들의 위에서 만들어져 공유 스레드 풀을 관리한다. 우리가 작업 아이템 혹은 코드 블럭을 DispatchQueue에 추가하면 GCD는 큐의 작업을 어떤 스레드에 할당할지 결정한다. 이로인해 개발자가 스레드를 생성하거나 관리해야할 부담을 줄여주고, 개발자는 단지 작업을 큐에 넘겨주기만 하면 된다.

Multithreading, Concurrency and Parallelism

CPU는 한 클럭 사이클에 한 작업만을 처리할 수 있다. 그러나, Multithreading은 프로세서가 서로 교환될 수 있는 동시성 스레드를 생성할 수 있게 해줘서, 여러 작업이 동시에 수행될 수 있다. 이는 사실 프로세서가 빠르게 두 작업을 바꿔가며 처리하는 것으로 실제로 ‘동시에’ 수행되는 것은 아니다. 하지만 이 작업이 매우 빨리 이루어지기 때문에 우리가 알아차리지 못할 뿐이다. 우리가 핸드폰을 사용할 때 CPU가 많은 양의 작업을 처리함에도 불구하고 여전히 부드러운 애니메이션과 상호작용이 가능한 UI가 나타나는 것은 모두 multithreading 덕분이다.

우리는 싱클 코어 환경에서 여러 작업을 바꿔가며 multithreading이 수행되는 것을 Concurrency라고 부른다. 그럼 멀티 코어 환경에서는 어떨까? 멀티 코어 환경에선 concurrency 처럼 빠르게 스레드를 교환하는 것이 아니라 실제로 스레드를 동시에 처리할 수 있고, 이를 Parallelism이라고 부른다. (물론 프로세서가 수행하는 작업의 종류에 따라 완전 병렬이 아닐 수는 있다.) Concurrency(동시성)은 논리적이 개념이고, Parallelism(병행성)은 물리적인 개념이다.

Concurrency_vs_Parallelism

DispatchQueue

GCD는 DispatchQueue를 운영하면서 개발자가 작업 단위를 큐에 제출하면 이 작업들을 FIFO 순으로 수행시킨다.(제출된 작업이 처음 시작되는 것을 보장한다)

Dispatch queue에는 serial queue, concurrent queue가 있다, 먼저 serial queue는 오직 하나의 작업만이 주어진 시간에서 실행될 수 있고 GCD가 실행 타이밍을 통제한다. 하나의 작업이 끝나고 다른 작업이 시작되는 사이의 시간을 알 수는 없고 모든 작업이 한번에 하나씩 시작되어 순서대로 종료된다.

Serial-Queue-Swift

반면에 concurrent queue에서는 여러 작업이 동시에 실행될 수 있다. 큐는 작업이 추가된 순서로 시작됨을 보장하지만, 작업들이 끝나는 순서는 동일하지 않다. 다음 작업이 시작되는데 걸린 시간을 알 수 없고, 주어진 시간에 몇개의 작업이 실행되는지도 알 수 없다.

Concurrent-Queue-Swift

위 그림을 보면 Task2, Task3는 이전 작업이 시작된 직후에 시작되는 것을 볼 수 있다. 반면에 Task1은 Task0이 시작한 후 일정 시간 후에 시작이 되었다. 또한 Task3는 Task2보다 늦게 시작했지만 더 일찍 끝나는 것을 볼 수 있다.

큐 내에서 작업이 언제 시작할 것인지는 모두 GCD가 결정한다. 만약 수행해야할 작업이 다른 작업과 실행시간이 겹친다면 GCD는 이 작업을 다른 코어에서 수행해야 하는지, 아니면 문맥 교환을 통해 수행해야 하는지 결정한다.

GCD는 3종류의 큐를 제공한다:

1. Main queue: 메인 스레드에서 실행되고 serial queue이다.

2. Global Queue: Concurrent queue이고 전체 시스템에 의해 공유된다. 네 가지(high, default, low, background)의 각기 다른 우선순위를 가진 queue가 존재한다. background 가 가장 낮은 우선순위다.

3. Custom Queue: serial, concurrent 두 가지 모두 가능한 직접 생성할 수 있는 queue이다. 이 큐에서의 요청은 실제로는 global queue중 하나에서 끝난다.

Global Queue에는 Qos 클래스 프로퍼티를 명시하는데, 이는 작업의 중요성을 명시하여 GCD가 주어진 작업의 우선순위를 결정할 수 있도록 도와준다.

Quality of Service의 우선순위 

  1. .userInteractive: 가장 높은 우선순위이며, 애니메이션, 이벤트, UI 업데이트와 같은 user-interactive 한 작업에 사용해야 한다.
  2. .userInitiated: 두 번째로 높은 우선순위이며, 빠른 반응 속도가 필요하거나, 유저가 앱에 기대하는 핵심 정보를 로딩할 때 등에 사용한다.
  3. .utility: 백그라운드 작업 같이 즉각 적인 결과를 필요로하지 않는 작업을 위한 QoS 이다. 반응성, 성능, 효율 사이의 균형을 위한 작업에 사용해야 한다.
  4. .background: 앱에서 보이지 않는 작업들을 위한 Qos. 에너지 효율에 우선순위를 둔다.

Dispatch queue에 제출되는 각각의 작업을 DispatchWorkItem이라고 하는데 우리는 QoS 클래스를 사용해서 DispatchWorkItem의 동작을 구성할 수 있다.

Synchronous vs Asynchronous

DispatchQueue에 작업을 전달할때 동기적(Synchronous)으로 보내는 방식과 비동기적(Asynchronous)으로 보내는 방식이 있다.

Synchronous는 작업이 완전히 끝날 때까지 현재 큐를 블럭한다. 작업이 반환/완료되면 control이 caller에게 반환되고 sync 작업 후의 코드가 진행될 것이다. *snyc를 blocking과 동의어라고 생각해라.

sync

반면 Asynchronous는 현재 큐를 비동기적으로 실행시켜 async 클로저의 내부가 실행되는 것을 기다리지 않고 caller에게 즉시 control을 반환한다.

async

OperationQueue

OperationQueue와 GCD Queue 모두 작업 단위를 캡슐화해서 실행을 위해 디스패치 할 수 있게 설계되어 있으며, UI Main 스레드와 분리되어 여러 스레드에서 무거운 작업을 수행하도록 해준다. GCD Queue는 저수준(Low-level) API인데 반해 NSOperation은 Objective-C 기반 추상 클래스이다.

NSOperation은 DispatchQueue와 달리 다음과 같은 특징이 있다.

  • Dependency

작업들 사이의 의존성을 추가할 수 있다. 이를 통해 작업의 수행 순서를 지정해줄 수 있다. NSOperationQueue는 따라서 많은 병렬 프로세싱이 필요한 작업(ex) 수학 방적식)을 위해 사용된다. 병렬작업들은 서로 의존되는 경우가 많기 때문이다. 예를 들어, 어떤 코드 블럭에 의존하는 작은 코드 블럭이 있다면 이것들을 다 실행하고 필요한 블록이 종료되길 기다릴 수 있다.

  • Pause, Cancel, Resume

GCD Dispatch는 작업을 보낸 후에는 통제할 수 없는데 반해 NSOperation을 중지, 취소, 재게할 수 있다. 또한, 동시에 수행될 최대 작업의 수를 지정할 수 있다.

  • Observable

NSOpration, NSOperationQueue 클래스는 KVO를 사용하여 관찰(observe)될 수 있는 여러 프로퍼티를 가진다.

요약

Concurreny는 여러 작업이 동시에 수행되는 것이다. 애플의 멀티코어 프로세서가 이를 가능하게 하고, 코어가 많을수록 더 많은 작업들이 동시에 수행될 수 있다. 이 작업들은 thread에서 수행된다. thread를 고속도로의 각 차로, 작업을 각 차로에서 달리는 자동차라고 생각하면 쉽다. Thread는 main thread와 background thread가 있다.

모든 thread를 개발자가 생성하고 관리하는 작업은 무척 어렵고 번거롭다. Apple에는 이 작업을 위한 GCD가 존재하고 GCD는 thread 생성과 관리 등 어려운 작업들을 처리해준다. 따라서 개발자는 단지 작업을 GCD가 운영하는 DispatchQueue에 작업을 전달만 하면된다. GCD 덕분에 동시성 프로그래밍을 아주 쉽게 할 수 있는 것이다.

Reference

Raywenderich

learnappmaking

코드스쿼드 YouTube

Tags:

Categories:

Updated: