duck typing

  • 특정 인터페이스의 메서드를 모두 구현하면 인터페이스로 사용될 수 있다. (암묵적 구현)
  • 잘못된 타입의 값을 인터페이스를 사용하는 함수로 전달한 경우 컴파일 타임에 오류가 발생한다. (암묵적 변환),(js/ python은 검사 못함)
  • 하지만 특정 인터페이스 값이 다른 인터페이스의 추가 메서드를 갖는지는 동적으로 확인한다.
  • 명시적인 인터페이스 간 변환은 런타임에 메서드 집합에 관한 정보를 확인할 수 있어야 한다.

메서드를 찾는 방법

  • C++의 vtable이나 js의 프로토타입 체인 사이 중간 정도의 방법을 사용한다.
    • 메서드 테이블을 사용하지만 런타임에 계산한다.

interface value

  • 인터페이스에 저장된 실제 타입에 대한 정보를 가리키는 포인터 (interface table)
  • 실제 데이터를 가리키는 포인터

i-table (interface table)

  • interface(myInterface, myConcrete)
    • var i myInterface = c 이면 c의 복사본을 저장
  • 실제 타입에 대한 메타데이터와 함수 포인터 리스트로 구성되어 있음
  • myInterface에 해당하는 메서드만 포함하며 다른 myConcrete의 메서드는 포함하지 않음

data

  • 하나의 워드 안에 포함되는 데이터면 힙 할당을 하지 않음
  • 값이 크면 힙에 메모리 할당 후 포인터를 저장

타입 비교 시

타입 확인

  • interface가 들고 있는 특정 타입을 확인하려면
    • i.tab->type으로 실제 타입 포인터 획득
  • 값은 i.data를 역참조하여 복사

    tab은 i-table 을 나타내는 멤버

디스패치

  • i-table에서 적절한 함수 포인터를 찾아 인터페이스 값의 data를 첫 번째 인자로 호출
    • i.tab->fun[0](i.data)
    • i.data는 32비트(워드) 포인터를 인자로 전달 받는 것
  • 호출 지점은 data의 의미나 가리키는 데이터의 크기를 모름
    • 인터페이스 코드는 itable의 함수 포인터가 인터페이스 값에 저장된 워드를 알고 있음
    • 함수 포인터 (*myConcrete).someFn

i-table 만드는 과정

  • 모든 조건(메서드)에 부합하는 (인터페이스 타입, 구체 타입) 쌍의 itable을 계산하는 것은 비효율적
    • 숫자가 많으며 실제로 필요하지 않을 수 도 있음
    • 이것도 결국 메모리에 올라가야 함
  • 각 구체 타입에 대해 type description structure를 생성
    • 다른 메타데이터와 함께 메서드 목록 포함
  • 각 인터페이스에 대해서 같은 작업
  • interface runtime은 두 테이블을 보고(i -> c) itable을 계산하여 캐싱
    • 이후에는 재사용
  • 모든 가능한 쌍은 O(ni * nc)
  • 두 테이블 정렬 후 비교는 O(ni + nc)

빈 인터페이스 최적화

  • 메서드가 하나도 없는 경우 i-table은 원래 타입에 대한 포인터를 저장하는 용도이다.
    • 메서드 존재 여부는 정적으로 파악할 수 있음
  • i-table을 생략하고 값이 타입의 메타데이터를 직접 가리키도록 한다.

값 인라인 최적화

  • 하나의 워드 안에 포함되는 데이터면 힙 할당을 하지 않음
  • 컴파일러는 타입의 메서드 테이블에 복사된 함수들이 전달받은 워드를 올바르게 처리하도록 조정
    • 함수 포인터 (myConcrete).someFn

메서드 조회

  • 인터페이스 값이 저장되는 시점에 itable을 계산하거나 캐시에서 찾고 메서드 호출 시 간접 호출만 수행

    간접호출 indirect call: 함수의 주소를 직접 명시하지 않고, 포인터나 테이블을 통해 함수의 주소를 찾아 호출

Go Data Structures: Interfaces

profile
https://velog.io/@oak_cassia/A-Game-Developers-Vision

0개의 댓글

Powered by GraphCDN, the GraphQL CDN