Method Disptach란 호출해야하는 메서드를 결정하는데 사용되는 알고리즘으로,
대표적으로 동적 디스패치와, 정적 디스패치가 있다.
Class는 동적 디스패치(Dynamic Dispatch) 메커니즘을 따른다.
동적 디스패치는 일명 런타임 디스패치 라고도 하는데 호출해야할 메서드를 런타임중 판단하는 것이다.
이때 발생하는 오버헤드로 인해 정적 디스패치에 비해 상대적인 성능 손실이 발생하게 되는데 Method Dispatch를 살펴보면서 알아보자.
해당 포스팅과 관련된 내용은 WWDC2016 영상 에서 더욱 자세하게 알 수 있다.
Static Dispatch
정적 디스패치는 컴파일 타임에 호출할 메서드를 결정짓게 한다.
컴파일러는 이때 실제로 어떤 구현이 실행될지 가시성을 가지기 때문에 코드를 최적화 할 수 있는 가능성을 지니고 있다. 예를 들면 inline 변환 같은것 말이다. 따라서 전체적인 프로그램의 속도를 빠르게 향상 시킬수 있게 된다.
그러나 정적 디스패치는 상속이 가능한 클래스에서는 사용할 수 없다. 때문에 Swift에서는 구조체나 열거형이 정적디스패치를 사용하게 된다.
Dynamic Dispatch
동적 디스패치는 위에서 말했듯이 런타임중 발생하는 오버헤드로 인해 성능이 뒤쳐진다고 했다. 그렇다면 런타임중 어떤 동작이 이뤄지길래 Static Dispatch보다 느린걸까?
클래스는 상속을 통해 하위 클래스에서 상속한 상위 클래스의 메서드를 새롭게 재정의 할 수 있는데, 이러한 재정의 개념을 지원하기 위해서 OOP의 언어들은 동적 디스패치를 활용하게 된다.
컴파일 시점에 클래스의 어느 메서드가 호출될지 알지 못하기 때문에 런타임 중 class마다 메서드 참조 테이블을 가진다.
이를 V-Table (Virtual Dispatch Table)이라 부르며, 클래스의 메서드는 런타임 중 어느 것이 실행되어야 할지 정해진다.
이 동작은 Static Distpach에 비해 추가적인 연산이 필요하게 되고 컴파일러가 최적화할 여지가 많지 않다.그렇다면 클래스는 항상 동적 디스패치를 사용해야만 할까? 꼭 그렇지도 않다.
동적 디스패치 줄이기
final 키워드 사용
클래스가 상속을 지원하지 않는다면 struct와 같이 정적디스패치를 사용토록 할 수 있다.
클래스는 자체만으로도 상속을 하지 않아도 동적 디스패치를 사용하는데 이유는 상속 가능성 때문이다.
우린 상속을 막기 위해 final 키워드를 사용할 수 있다. class 앞에 final을 선언하면 컴파일러는 클래스 상속가능성이 없다는것을 인지하고 동적디스패치가 아닌 정적 디스패치 메커니즘을 적용하게 된다.
접근제어자 사용
private키워드를 적용하면 선언의 가시성을 제한하여 컴파일러가 재정의 할 수 있는 가능성을 유추한다. 만약 재정의 선언이 없다면 컴파일러에서 final키워드를 자동으로 유추하게 된다.
WMO(Whole Module Optimization
전체 모듈 최적화를 사용하는 방법. 모듈은 Swift파일의 집합이다. 각 모듈은 단일 배포단위로 컴파일되는데, Swift컴파일러는 모듈의 각 파일에 대해 개별적 호출을 한다.
개별적 호출이란 것은 file_1.swift에서 작성한 클래스가 file_2.swift 파일에서 사용하는지 컴파일단계에서 판단하지 못한다는것이다.
만약 클래스가 다른 파일에서 사용되지도 상속되지도 않는다는것을 알 수 있다면 컴파일단계에서 최적화를 할 수 있지 않을까?
WMO는 전체 모듈을 확인한다. 모든 모듈의 함수 구현을 확인하므로 함수 인라인과 같은 최적화를 수행할 수 있다. 반드시 인라인하지 않더라도 컴파일러가 함수의 구현을 미리 파악하게 된다면 많은 도움이 된다. 예를 들어 참조 카운팅 관련 동작에 대해 추론이 가능하다.
만약 아무곳에서도 상속 되지 않은 함수또는 클래스는 내부적으로 final을 유추하여 정적 디스패치 로 동작하게 끔 할 수있다.
'난 iOS개발자 > iOS' 카테고리의 다른 글
ARC(Auto Reference Counting) (0) | 2022.05.05 |
---|---|
String을 Subscript로 접근할 수 없는 이유 (0) | 2022.05.04 |
initialization -3 (0) | 2022.04.29 |
initialization-2 (0) | 2022.04.27 |
initialization-1 (0) | 2022.04.25 |