이전 값 타입과 참조 타입 글에서 struct보다는 class를 사용하라는 말을 했지만, 특정 프로토콜을 채택해야 하는 상황 등 분명히 class를 사용해야만 하는 경우가 발생한다
앱을 모델링할 경우에 이러한 class 성능을 향상시키기 위한 노력이 반드시 필요하다
지금부터 class의 성능을 향상시키는 방법을 알아보자~ 😎
Static Dispatch vs Dynamic Dispatch
함수를 호출하는 방식인 Static Dispatch와 Dynamic Dispatch을 이용하여 class의 성능을 향상시킬 수 있다.
이러한 함수 호출 방식들에 대해 살펴보자
Dynamic Dispatch
Swift에서 class는 상속 기능을 지원하고, 상속한 하위 클래스에서 상위 클래스의 메서드를 오버라이딩해서 사용하기도 한다
class MyClass {
func sayHello() {
print("Hello~")
}
}
class YourClass: MyClass {
override func sayHello() {
print("Hello Hello~")
}
func sayBye() {
print("Bye~")
}
}
class HerClass: YourClass {
override func sayHello() {
print("Hello~~~~~~")
}
override func sayBye() {
print("Bye Bye~")
}
func myMethod() {
print("this is method~")
}
}
let hc = HerClass()
hc.sayHello() // Hello~~~~~~ 출력
위와 같이 하위 클래스의 하위 클래스의 인스턴스가 오버라이딩한 메서드를 실행하면 컴파일러는 어떤 메서드를 실행해야 될까?
이 때 하위 클래스의 Virtual Dispatch Table이라는 함수 포인터들을 배열 형태로 저장해놓는 테이블에 접근하여 실제 호출할 함수를 결정한다
MyClass | YourClass | HerClass |
sayHello() | override sayHello() sayBye() |
override sayHello() override sayBye() myMethod() |
[ Virtual Dispatch Table 예제]
이러한 테이블을 통해 상위 클래스인 YourClass나 MyClass의 sayHello() 메서드가 아닌 HerClass에서 재정의한 sayHello() 메서드를 실행한다
즉, 상속한 하위 클래스의 메서드를 실행되는 순간 컴파일러는 위의 Virtual Dispatch Table을 참조하여 실제 호출할 함수를 결정한다. 이것을 Dynamic Dispatch라고 한다
Dynamic Dispatch는 런타임에 작동되므로 속도가 느리다 ( = 성능이 좋지 않다)
Static Dispatch
반면에 Static Dispatch는 컴파일 타임에 호출될 함수를 결정하여 실행하는 함수 호출 방식이다
상속이나 다형성을 구현할 수 없지만, 속도가 매우 빠르다
주로 구조체나 열거형이 함수를 호출하는 방식이다
class의 함수 호출이라도 Dynamic Dispatch이 아닌 Static Dispatch로 작동시켜 class의 성능을 향상 시킬 수 있다
1. 상속이나 오버라이딩이 필요없는 클래스의 메서드, 프로퍼티에 final 선언하기
final
- final + class -> 상속이 불가능한 class를 의미
- final + 메서드/프토퍼티 -> 오버라이딩 불가능
final 키워드를 붙이면 하위 클래스가 해당 final class를 오버라이딩 할 수 없으므로 Static Dispatch로 동작한다
-> 성능 향상 효과
2. 파일 내에서만 접근할 경우 private으로 선언하기
private
- private으로 선언 시, 참조 가능한 범위가 현재의 파일로 제한
- 컴파일러가 해당 프로퍼티가 참조될 수 있는 구역 내에서 오버라이딩이 되는 지 판단할 수 있음
- 만약 오버라이딩이 되는 곳이 없다고 판단할 경우 final class로 추론
- Static Dispatch로 동작
private 키워드가 있는 객체는 final 키워드가 없더라도 오버라이딩 되지 않고 있을 경우 자동으로 Static Dispatch로 동작한다
-> 성능 향상 효과
정리해보면, class의 성능을 향상시키기 위해서는 런타임에 실행할 함수를 찾는 Dynamic Dispatch 방식보다는 컴파일 타임에 실행되는 Static Dispatch를 사용해야 한다
그 방법에는 final 로 선언하기와, private으로 선언하기 등이 있다
이러한 방식들로 되도록이면 Static Dispatch 방식을 사용하여 method를 호출하도록 해야겠다!
참고
https://developer.apple.com/videos/play/wwdc2016/416/
https://velog.io/@wnsxor1993/Class%EC%9D%98-%EC%84%B1%EB%8A%A5-%ED%96%A5%EC%83%81-%EB%B0%A9%EB%B2%95
'Swift' 카테고리의 다른 글
[Swift] 비동기 프로그래밍의 이해 (0) | 2023.05.05 |
---|---|
[Swift] self vs Self (0) | 2023.05.05 |
[Swift] 타입 캐스팅 (0) | 2023.05.05 |
[Swift] 프로퍼티 (0) | 2023.05.05 |
[Swift] 값 타입과 참조 타입 (0) | 2023.05.02 |