- GCD는 앱 개발자가 쉽게 앱을 스케일링 하게 하기 위해 만들어짐
- Parallelism and concurrency
- Parallelism: 병렬. 긴밀하게 연관된 작업의 동시 실행
- 관련 프레임워크
- Accelerate
- Core ML
- Core Animation
- GCD에서는?
DispatchQueue.concurrentPerform(1000) { i in ... }
dispatch_apply(DISPATCH_APPLY_AUTO, 1000, ^(size_t i) { ... }
- 코어 상태에 따라서 자동으로 밸랜싱
- 코어 타임의 빈 부분을 자동으로 찾아서 스케쥴링 해준다.
- Concurrency: 병행, 독립적으로 동작하는 작업들의 조합
- Context switching을 통해서 앱의 반응성을 유지할 수 있다.
- OS가 스레드를 선택한다.
- 다만 지나친 context switching은 비용이 많이 들어서 CPU 효율을 떨어뜨린다.
- 반복적으로 상호 배제적으로 리소스에 접근
- fair lock은 모든 스레드에 균등한 기회를 주는 대신에 컨텍스트 스위칭을 발생시킬 여지가 많다.
- pthread_mutex_t, NSLock, DispatchQueue.sync
- unfair lock은 lock을 바로 해제하지 않고 가지고 있다가 다시 lock을 걸 수 있다. 그래서 균등한 기회를 주지는 않지만 컨텍스트 스위칭을 줄일 수 있다.
- lock ownership에 대한 재고
- lock의 소유자에게는 우선순위를 낮추고, lock 대기자에게는 우선순위를 높인다 -> 즉, 자주쓰면 lock을 얻기 쉬워진다.
- 구분
- 단일 소유: Serial Queue, DispatchWorkItem.wait, os_unfair_lock, pthread_mutex_NSLock
- 소유 없음: dispatch_semaphore, dispatch_group, pthread_cond, NSCondition, Queue suspension
- 다중 소유: Private concurrent queue,, pthread_rwlock
* 반복적인 스위칭
* 스레드끼리 작업을 반복적으로 주고 받는 것
- GCD
- Serial
- 상호 배제
- FIFO
- enqueue는 원자적으로 여러곳에서, dequeue는 한 스레드에서만 함
- Dispatch source: 이벤트를 모니터링하기 위한 primitive
- 이벤트 핸들러, 캔슬 핸들러 설정 기능
- 명시적인 초기화(activate())
- 시리얼 큐와 소스는 트리를 구성할 수 있다.
- 단일 컨텍스트를 공유함(상호 배제적)
- 각 큐는 독립적인 순서를 가짐
- 예시: 수 많은 네트워크 요청을 여러큐에서 할 때, 마지막에 하나로 묶어주는 큐를 두는 것 -> 컨텍스트 스위칭 방지
- QoS
- 우선순위에 대한 추상화된 표시
- 일에 대한 명시적인 분류
- 작업을 실행할 때 많은 부분에 영향을 미침
- 종류
- User Interactive(UI)
- User initiated(IN)
- Utility(UT)
- Background(BG)
- 순서대로 실행은 되지만, 높은 Qos가 할당된 Queue가 우선권을 가지게 된다.
- 글로벌 큐에 너무 많이 넣으면 이벤트가 블록 될때 마다 스레드가 생성된다.
- 서브시스템당 하나의 큐를 유지하고, 트리 형태로 묶어주자
- queue 계층을 고정하자
- workItem을 적당한 크기로 합쳐줘야 한다.
- Unified Queue Identity
- 기존에는 Application부분에서만 큐를 다뤘는데, 이제는 커널 영역에서도 관련 오브젝트가 존재
- 스레드와 큐가 연결되서, 큐는 자기의 이벤트가 어떤 스레드에서 실행될 지 알 수 있게 된다.
- 나이스한 사용방법
- DispatchSource 를 activate 한 이후에는 바꾸지 마라
- event handler와 target을 미리 지정하라
- Queue 그래프를 동적으로 바꾸지마라
- 우선순위와 소유권에 대한 스냅샷이 쓸모없어지면서 최적화가 어려워진다.
- Tooling
- GCD Perfomance instruments