Swift - Method Dispatch

이희수·2023년 4월 5일
0

Swift

목록 보기
4/4

클래스와 프로토콜의 메서드가 실행되는 방식에 대한 이해


어떤 경우에는 느리거나 효율성을 따져볼수 있는지... 고민을 해봐야한다
깊은 부분을 이해하면 컴퓨터가 어떤 방식으로 메서드들이 동작을 하는지.. 좋은 개발자가 되기위해 기본적인 지식을 쌓는 과정이라고 생각하자

즉.. 큰 그림을 알고있자

코드 데이터 힙 스택 영역이 있다
실제로 이 메서드는 Cpu에 대한 명령어다
해당 코드들은 코드영역에만 존재한다
코드영역에 저장되어있는 함수, 메서드를 실행시키려면 메서드 주소가 필요

어떤 클래스에 메서드를 실행시킬때 어떤 메서드를 실행시키는지.. 이러한 관련내용을 기록해보자


함수, 메서드를 실행시키는 방법은 크게 3가지로 나뉜다

  1. Direct Dispatch 또는 Static Dispatch
    (어떤 테이블을 거치지 않는다)
    가장 빠름 0.0 ~ 2.13ns (나노 세컨즈)

컴파일 타임에 일어난다

작성한 코드는 기계어로 해석을 한다 (컴파일 타임)
그때 어떤 메모리에 메모리 주소를 인식한다
함수 메모리 주소를 삽입하거나 함수의 명령 코드를 해당위치에 삽입한다

코드영역의 명령어가 있고 이것을 박스로 묶은거처럼 상상하면 이것이 함수나 메서드라고 생각하자
명령어가 시작되는 부분에 90번 메모리 주소의 함수가 들어있다

해당 함수를 실행 시키려면 90번 이라는 메모리 주소를 기억하고 있어야한다

더 빠르게 실행하려면 ?

90번째 메모리에 있는 함수 명령어 묶음을 해당 줄에 넣어버린다
긴 함수가 아니면 명령어를 복사해서 붙히면 이 과정에서 메모리가 많이 들지 않는다

명령 코드를 해당위치에 코드를 심어 버리는것(in-line)

구조체나 열거형의 메서드가 이런식으로 실행이 된다
상속이나 다형성의 구조가 없을때 사용된다


  1. Table Dispatch

런타임에 발생된다

실제로 앱이 실행되고 있는 동안에 메모리 주소를 찾아 실행시키는 구조

Message Dispatch와 어떤 차이가 있을까

Message Dispatch는 예전 objective-c에서 쓰이던 방식이다
참고하자

Table Dispatch는 클래스와 관련된 메서드 테이블들은 버츄얼 테이블이 있다
클래스 테이블 : Virtual Table

클래스 테이블 안에선 메서드의 이름과 주소가 저장되어 있다
배열 형태로 저장된다
자식 클래스에서도 따로 메서드의 배열로 저장이된다

Message Dispatch는
메서드1을 그대로 가져와 자식 클래스의 테이블에 그대로 가져오는것이 아닌 예시로 부모 클래스에서 메서드를 재정의 하면 따로 자식 클래스의 테이블에서 생성을 한다

재정의 하지 않은 메서드라면?
자식 클래스의 테이블에서 기억을 하지 않고 super클래스를 찾아간다
자식 클래스의 테이블에서 재정의하지 않은 메서드를 실행시키면 해당 테이블에 없으니 다시한번 부모 클래스를 찾아가 재정의 하지 않은 메서드를 찾아서 실행을 시킨다

자식 클래스 테이블에서 테이블을 찾고 없으면 다시 부모클래스를 찾아가 해당 메서드들을 찾아야 하므로 속도가 느리다


Table Dispatch를 두가지로 나누면

클래스에서 사용하는 Virtual Table을 사용하고
프로토콜을 채택을 해서 구현하면 추가적으로 Witness Table을 만든다
프로토콜을 채택했을때 어떤 메서드를 실행시킬지 보는 테이블이다

  1. Virtual Table
  2. Witness Table

함수의 메모리 주소를 포인터 라고한다
각 테이블에 이 포인터가 저장이되서 코등영역에 찾아가 메서드를 실행 시킨다


  • 구조체나 열거형은 벨류타입이고 메서드를 구현하면 상속개념이 없기 때문에
    Direct Dispatch방식으로 동작을 한다

  • 프로토콜 같은경우 본체에서 요구사항으로 요구하는 메서드를 구현하면
    Witness Table을 만듬
    프로토콜 확장에서 요구사항으로 선언되어 있지 않은 메서드는 Direct Dispatch로 동작

본체의 요구사항 메서드를 Witness Table로 구현
프로토콜을 채택한 타입마다 테이블을 만듬

  • Class는 Virtual Table로 동작한다
    Class의 확장에서는 상속할때 메서드들은 재정의가 불가능하기 때문에
    상속 구조를 무시할수 있어 Direct Dispatch로 동작을 한다

단, @objc dynamic키워드를 이용해 Message Dispatch방식으로 변경시 확장(extension안에 메서드 재정의가 가능)

@@ 클래스를 상속을 하지 않기하기 위해서는 final 키워드를 정의한다
이럴때는 Direct Dispatch로 동작 해당 자리에다가 함수의 포인터를 삽입한다

  • Message Dispatch방법을 굳이 구현을 하려면?
    @objc dynamic키워드를 이용해서 구현할순 있지만 현재 지금 프로젝트에서는 거이 쓸일이 없다

해당 프로토콜 채택시

Witness Table을 생성 그 안에 메서드들이 있다

채택한 클래스에서 버츄얼 테이블 안에 메서드들은 두개 다 완전히 동일하다

채택하면 프로토콜 테이블에서 버츄얼 테이블이 해당 메서드를 가져온다 (동일한 메서드 주소가 들어있다)

_해당 인스턴스에서
class형식으로 저장이 되어있을때 class참조
프로토콜 형식으로 저장이 되어있을때 프로토콜 타입 참조
__**

0개의 댓글