본문 바로가기
Swift

[Swift] Dynamic Dispatch vs Static Dispatch

by Sky Titan 2021. 12. 5.
728x90
 

[iOS - swift] Static Dispatch, Dynamic Dispatch 성능 최적화 방법, Witness Table, (final, private을 사용하는 이유)

final class vs class final class A { ... } class B { ... } class A와 class B의 차이점 A는 서브클래싱이 불가능 A는 성능적으로 더욱 높은 장점 -> 성능이 좋은 이유? 성능이 좋은 이유 - static dispatch 사..

ios-development.tistory.com

 

Swift의 Dispatch 규칙

지난 포스트에서 Dynamic Dispatch를 피해서 성능 최적화를 하는 방법을 알아보았습니다. 하지만 swift가 Dynamic Dispatch만 사용하는 것은 아닙니다. Swift는 다양한 Dispatch 방식을 사용하는데, 이번 포스

jcsoohwancho.github.io

 

Dynamic Dispatch와 성능 최적화

많은 객체 지향 언어들이 메소드와 프로퍼티들을 오버라이드 할 수 있도록 허용합니다. Swift도 예외는 아닙니다. 그런데 이렇게 오버라이드를 할 경우, 프로그램은 실제 호출할 함수가 어떤 것

jcsoohwancho.github.io

개요

  • 기본적으로 객체지향 패러다임이 적용되어있는 언어들은 메소드와 프로퍼티들의 오버라이드를 지원한다.
  • 이렇게 오버라이드된 메소드들이 호출될 때, 프로그램의 입장에선 실제 호출할 함수가 상위 클래스의 메소드인지 아니면 현재 클래스의 메소드인지 의사결정하는 과정이 필요하다.
  • 해당 의사결정 타입은 Static Dispatch와 Dynamic Dispatch가 있다.

 

import UIKit

class Parent {
    
    var name: String = "Parent"
    
    func printAge() {
        print("My Age is 15")
    }
}

class Child: Parent {
    override var name: String {
        get {
            return "Child"
        }
        
        set {
            super.name = newValue
        }
    }
    override func printAge() {
        print("My Age is 13")
    }
}



let p: Parent = Child()


p.printAge()
print(p.name)

/* 1. Static Dispatch
My Age is 15
Parent
*/

/* 2. Dynamic Dispatch (Swift의 결과)
My Age is 13
Child
*/

 

Static Dispatch (Direct Call)

  • 변수의 명목상 타입에 맞추어 함수를 호출한다.
  • 컴파일 시에 어떤 것을 호출할지가 결정된다.
  • 현재 Parent 클래스 타입으로 선언되어있다면 Parent 클래스의 함수를 호출하게 된다.
  • Child 클래스의 요소를 호출하고 싶다면 타입 캐스팅을 활용해야한다.
  • 따라서 객체지향의 다형성을 활용하기 어려워지는 방식이다.

 

Dynamic Dispatch (Indirect Call)

  • 변수의 실제 타입에 맞추어 함수와 프로퍼티를 호출한다.
  • 런타임 시에 어떤 것을 호출할지가 결정된다.
  • 어떤 서브클래스가 들어와도 실제 타입에 맞는 요소를 호출한다.
  • 다형성 활용에 유리하다.
  • 하지만 런타임 시에 실제 참조할 요소를 찾는 과정이 필요하여 Static Dispatch에 비해 O(1)의 시간복잡도가 더 소모되어 속도면에선 불리하다.
    • 때문에 최적화 시에 가능하다면 Static Dispatch를 활용할 수 있도록 해야한다.
  • Swift는 Dynamic Dispatch를 차용한다.

 

Dynamic Dispatch가 필요하지 않은 경우의 최적화 가능한 방법

  1. 오버라이드 될 필요가 없는 요소들은 final 키워드를 붙인다.
    • 컴파일러는 final 키워드를 보고 오버라이드 될 필요가 없는 요소라는 것을 알고 최적화 하게 된다.
  2. private 키워드를 붙이면 해당 요소는 한 파일 내에서만 참조되는 것이 보장된다.
    • 따라서 해당 요소에 대한 오버라이드가 파일 내에 존재하지 않는다면 자동으로 컴파일러가 Direct Call로 바꾸어 준다.
  3. WMO(Whole Module Optimization)을 사용한다면 internal 선언만으로 Direct Call을 보장할 수 있음
    • 다만 모듈 내에서 오버라이드가 없는 경우에 한해서이다.
    • swift에선 모듈을 이루는 파일들을 개별적으로 컴파일하기 때문에 다른 파일에서 오버라이딩이 일어났는지 알 수 없지만 모듈은 모듈 통째로 컴파일을 하기 때문에 모듈 내에서 internal선언을 하게 되면 다른 모듈에선 오버라이딩이 불가능하다는 것을 확인해준다.
728x90

'Swift' 카테고리의 다른 글

[Swift] Property Wrapper  (0) 2022.02.13
[Swift] self vs Self  (0) 2021.12.08
[Swift] 클로저 (Closure)  (0) 2021.07.12
[Swift] Any, AnyObject  (0) 2021.06.21
[Swift] defer  (0) 2021.06.21

댓글