Swift 6 어때요? (2): executor, job, hop_to_executor
두줄요약
Swift Concurrency의 executor와 hop_to_executor 동작을 런타임 소스로 살펴본 글입니다. executor는 job을 실행하는 추상화이며, 스레드 폭증을 막고 hop은 대부분 스레드 전환이 아니라고 정리했습니다.
핵심 내용
- Swift Concurrency의 실행 모델을 런타임 소스와 SIL로 추적하며 executor, job, hop_to_executor 관계를 정리
- executor는 job을 실행하는 추상화이고, 스레드 생성 책임은 없으며 global executor는 스레드 폭증을 막는 방향으로 동작
- hop_to_executor 는 스레드 전환 명령이 아니라 executor 전환 명령이며, 목적지 executor가 바쁠 때만 큐잉 발생
구조와 흐름
- async 함수는 resume 지점마다 분할된 partial function으로 컴파일되고 async context에 상태 보관
- 각 partial function은 다음 실행 대상 executor를 값으로 들고 있으며 SIL의 hop_to_executor 로 이동
- isolation에 따라 global executor, task executor preference, actor의 executor로 job 분기
성능/운영 포인트
- global executor는 job이 늘어도 스레드 수를 늘리지 않고, blocking 코드가 전체 진행을 지연시킬 수 있음
- Task.sleep 과 Thread.sleep 실험에서 suspend는 소수 스레드로 다수 작업 처리, blocking은 스레드 고정으로 대기 발생
- hop 자체는 대부분 같은 스레드에서 처리되며 실제 비용은 목적지 executor가 바쁠 때만 증가
주의할 점
- async 문맥에서 스레드를 붙드는 blocking 작업은 global executor의 처리량 저하로 이어질 수 있음
- hop이 많다는 사실만으로 곧바로 스레드 context switching 비용을 단정하기 어려움



