안녕하세요.
이번엔 Thread.sleep과 Task.sleep의 차이점에 대해 알아보려고 합니다.
# 주요 차이점
Thread.sleep | Task.sleep |
iOS 2.0 이상 | iOS 13.0 이상 |
구 API | 신 API |
cancel 불가능 | Task cancel 가능 |
주어진 시간 만큼 Thread 멈춤 | 현재 Task를 중지하고, 주어진 시간 동안 다른 Task 수행 (Thread를 멈추는 것이 아님) |
# 예시
1초 sleep을 100번 수행했을 때 Thread.sleep과 Task.sleep이 어떻게 다르게 동작하는지 살펴볼게요.
가장 이상적인 동작은 1초만 sleep 하는 것이겠죠?
(100개의 Task(or Thread)에서 동시에 1초를 sleep 하면, 실제 시간으로 1초만 sleep 한 거랑 동일하죠.)
아래는 결과물입니다.
Thread.sleep Duration: 9.02s
Task.sleep Duration: 1.04s
시간 차이가 꽤 많이 나죠??
Thread.sleep 먼저 분석해 보자면.
제 맥북은 12 logical core 입니다. 그 뜻은 동시에 12개의 작업을 할 수 있다는 말입니다.
9.02초가 나온 이유는, core 12개가 동시에 1초 sleep을 8번 반복하고 마지막으로 core 4개가 1초 sleep을 한 시간이라고 볼 수 있을 것 같습니다.
(마지막에 core 4개라고 한 이유: 100 - 12 x 8 = 4)
(0.02초는 아마 thread switching 비용이지 않을까 싶습니다.)
Task.sleep도 살펴볼게요.
Task.sleep은 Thread.sleep과는 다르게 Thread를 멈추는 것이 아니고 Task를 멈추는 것입니다.
쉽게 풀어쓰자면 이런 식이 될 것 같아요.
1. 부모 task가 withThrowingTaskGroup 내부 실행.
2. 부모 task가 1번 자식 task한테 일(=Task.sleep)을 줌.
3. 부모 task가 2번 자식 task한테 일(=Task.sleep)을 줌.
...
101. 부모 task가 100번 자식 task한테 일(=Task.sleep)을 줌. -> 반복문 종료.
102. 부모 task는 모든 자식 task가 종료될 때까지 대기.
103. 1번 자식 task 종료, 2번 자식 task 종료,..., 100번 자식 task 종료
여기서 중요한 것은 부모 task가 자식 task한테 일을 줄 때 이전 자식 task의 일이 끝나지 않았음에도 다음 자식 task한테 일을 할당한다는 것입니다.
그렇기 때문에 1.04초 만에 모든 동작이 완료된 것이죠. 0.04초는 Task switching 비용 때문이겠죠..?
(모든 자식 task가 거의 동시에 시작하고 거의 동시에 끝났기 때문입니다.)
한 가지 궁금한 거!!!
만약 1초 sleep을 100번이 아닌 core 수(=12) 만큼만 해주면 어떻게 될까요??
아래는 결과입니다.
Thread.sleep Duration: 1.00s
Task.sleep Duration: 1.02s
이번엔 반대로 Thread.sleep이 더 빨리 끝났네요!!
아마, Thread.sleep의 경우 모든 core를 한 번에 다 사용해서 동작을 완료시켰기 때문에 1초 만에 끝나버린 것 같네요.
(thread switching도 필요 없으니까요)
이런 결과를 봤을 때, 일반적으론 Task.sleep의 성능이 더 좋으나 예외적인 상황에선 Thread.sleep의 성능이 더 좋을 수도 있겠다 싶었습니다.
# 참고
- https://trycombine.com/posts/thread-task-sleep/
- https://developer.apple.com/documentation/foundation/thread/1413673-sleep
- https://developer.apple.com/documentation/swift/task/sleep(_:)
- https://developer.apple.com/documentation/swift/task/sleep(until:tolerance:clock:)
이번 글은 여기서 마무리.
'Swift' 카테고리의 다른 글
Dictionary Enum.rawValue subscript (0) | 2023.08.08 |
---|---|
Opaque and Boxed Types (0) | 2023.07.01 |
[Swift 5.8] weak self 사용 시 self 생략 가능해짐 (0) | 2023.05.15 |
KeychainAccess Array 저장 API 추가하기 (0) | 2023.04.20 |
CasePaths 맛보기 (0) | 2023.04.02 |