study record

[Swift] Dynamic Dispatch란? 본문

Swift/스위프트 정리

[Swift] Dynamic Dispatch란?

asong 2022. 4. 14. 11:17

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