study record
[Swift] Dynamic Dispatch란? 본문
Dispatch란?
Dispatch란 어떤 메서드를 호출할 것인지를 결정하여, 그것을 실행하는 메커니즘이다.
Swift에서는 Static Dispatch와 Dynamic Dispatch 두 가지 방식이 있다.
즉, 호출할 함수를 "컴파일 타임"에 결정하느냐, "런타임"에 결정하냐에 따른 방식이다.
Static Dispatch(Direct Call)
"컴파일 타임"에 호출될 함수를 결정하여, 런타임 때 그대로 실행한다.
컴파일 타임에 결정이 되기 때문에 성능상 이점을 가질 수 있다.
Dynamic Dispatch(Indirect Call)
"런타임"에 호출될 함수를 결정한다.
Swift에서는 클래스마다 함수 포인터들의 배열인 vTable(Virtual Dispatch Table)을 유지한다.
하위 클래스가 메서드를 호출할 때, 이 vTable을 참조하여 실제 호출할 함수를 결정한다.
이 과정들이 "런타임"에 이루어지기 때문에 성능상 손해를 보게 된다.
Reference Type의 Dispatch
Reference Type의 클래스는 상속의 가능성이 있다.
따라서 서브 클래스에서 함수를 호출할 수 있기 때문에 Dynamic Dispatch를 사용한다.
즉 클래스는 Dynamic Dispatch를 사용한다. 오버라이딩의 가능성, 상속의 가능성이 있기 때문이다.
컴파일러는 클래스의 메서드가 하위클래스에서 오버라이딩이 될 경우를 대비해, 상위 클래스의 메서드를 참조해야 하는지, 하위 클래스의 메서드를 참조해야 하는지를 확인하는 작업을 해야 한다. 이것을 런타임에 실행한다. 따라서 각 클래스마다 가지고 있는 vTable 안에 함수 포인터로 함수를 두고, 실제 런타임 시점에 이 vTable을 사용하여 어떤 메서드가 불리는지를 결정한다. 메서드가 오버라이딩되지 않을 수도 있지만 클래스는 오버라이딩 될 수 있는 가능성이 있기 때문에 실제 오버라이딩이 됐는지 여부에 상관없이 무조건 vTable을 확인하여 참조한다. 모든 하위 클래스에는 상위클래스의 vTable 복사본이 있고 이 클래스의 오버라이딩 메서드들을 가리키는 함수 포인터가 있다. 하위클래스가 새 메서드를 추가하면 해당 메서드 포인터가 vTable의 끝에 추가되는 방식이다.
이처럼 런타임 시점에 해당 클래스의 vTable에서 함수를 찾아 메모리 주소를 읽고, 그 주소로 점프해야 하기 때문에 두 개의 추가 명령이 필요해 성능상 손해를 보게 된다.
그렇지만 Dynamic Dispatch는 오버라이딩을 위해서는 필수적이다. 상속하지 않을 경우에 함수 호출 때마다 Dynamic Dispatch로 동작한다면 성능 손해라고 생각할 수 있다. 상속이 필요 없는 클래스라면 Static Dispatch로 동작하게 하여 성능 향상을 시키는 것이 좋다.
따라서 상속, 오버라이딩 될 필요가 없는 클래스, 메서드, 프로퍼티에 final 키워드를 붙여 성능 최적화를 할 수 있다. final이 붙은 클래스는 상속이 불가능하고, 메서드, 프로퍼티에 붙을 경우에 더이상 하위 클래스에서 오버라이딩 할 수 없기 때문이다. 오버라이딩이 불가하여 Static Dispatch로 동작하게 된다.
또한 private 키워드를 붙이면 참조할 수 있는 곳이 현재 파일로 제한된다. 따라서 컴파일러는 private 키워드가 참조될 수 있는 곳에서 오버라이딩이 되는지 안 되는지를 판단한다. 오버라이딩 되는 곳이 없다면 스스로 final 키워드를 추론하여 Static Dispatch로 동작한다고 한다.
익스텐션으로 메서드를 추가할 경우 오버라이딩이 불가능하다. 따라서 이 경우에서는 Static Dispatch로 동작한다.
Value Type의 Dispatch
Valye Type인 구조체, 열거형은 상속을 할 수 없다는 특징 때문에 오버라이딩이 될 가능성이 없으므로 Static Dispatch를 사용한다.
런타임에 따로 추적할 필요가 없으므로 컴파일 타임에 결정이 된다.
참고:
https://babbab2.tistory.com/143
https://babbab2.tistory.com/145?category=828998
'Swift > 스위프트 정리' 카테고리의 다른 글
[Swift] 클로저, 탈출 클로저와 메모리 (0) | 2022.05.23 |
---|---|
[Swift] Swift 메모리 관리 - ARC란? (0) | 2022.05.18 |
[Swift] Delegate와 Retain 여부! (0) | 2022.03.15 |
[Swift] 탈출 클로저(escaping closure)란? (0) | 2022.03.09 |
[Swift] 순환참조 (Retain Cycle) + (클로저 weak self) (0) | 2022.03.05 |