[WWDC 2016] Understanding Swift Performance - Generic (3)
WWDC 2018 Understanding Swift Performance 를 정리한 포스트입니다.
더 자세한 내용을 원하시면 위 링크를 참조하시길 바랍니다.
1. [WWDC 2016] Understanding Swift Performance - Struct, Class (1)
2. [WWDC 2016] Understanding Swift Performance - Protocol (2)
2. [WWDC 2016] Understanding Swift Performance - Generic (3)
Generic Code
foo, bar 함수는 T: Drawable 제약조건의 Generic 을 가질 수 있습니다.
foo, bar 함수 매개 변수는 T를 사용합니다.
foo(local:) 를 실행하면 호출하는 쪽의 Generic Type T 는 Point Type으로 바인딩됩니다.
foo(local:) 내부에 bar(local:) 함수가 호출되면서 Parameter local 변수는 Point Type 을 갖게 됩니다.
하나의 참조 Type만 가지고 있기 때문에 Swift는 Existential Container를 사용하지 않습니다.
호출하는 측에서 사용되는 Type의 The Value Witness Table (VWT)과 Protocol Witness Table(PWT)을 함수에 대한 추가 인수로 전달할 수 있습니다.
drawACopy 함수가 실행되면서 매개 변수에 대한 로컬 변수를 만들 때
Swift는 The Value Witness Table (VWT)을 사용하여 힙에 필요한 버퍼를 할당(Allocate)하고 할당 소스에서 대상으로 복사(Copy)를 실행합니다.
local.draw() 실행할 경우도 마찬가지로 전달 된 Protocol Witness Table(PWT)을 사용하고 테이블에서 고정 오프셋의 draw 메서드를 찾은 다음 구현으로 이동합니다.
Swift는 로컬 매개 변수에 필요한 메모리를 스택에 valueBuffer를 할당합니다.
Line과 같은 큰 값은 다시 힙에 저장되며 로컬 Existential Container 내부의 해당 메모리에 대한 포인터를 저장합니다.
Specialization of Generics
Swift는 호출하는 측에서 사용되는 Type 으로 버전을 만듭니다.
(Static polymorphism: uses type at call-site)
drawACopy -> drawACopyOfAPoint 의 함수를 생성합니다.
(Creates type-specific version of method)
Point의 Line에서 drawACopy 함수를 호출하면 해당 함수의 두 가지 버전을 사용합니다.
(Swift 가 생성해준다.)
Point 메소드의 drawACopy가 더 이상 참조되지 않으므로 컴파일러는이 메소드를 제거하고
Line 예제에 대해 유사한 최적화를 수행합니다.
local: Point 는 다른 곳에서 참조하기 않기 때문에 컴파일러에 의해서 최적화 될 수 있습니다.
// before
let local = Point()
local.draw()
drawACopyOfALine(Line(…))
// after
Point().draw()
drawACopyOfALine(Line(…))
Whole Module Optimization
전체 모듈 최적화 기회를 크게 향상시킬 수있는 기회가 있습니다.
Point 의 정의를 별도의 파일로 옮긴경우
Whole Module Optimization 를 사용하면 컴파일러는 두 파일을 하나의 단위로 함께 컴파일하고
Point 파일의 정의에 대한 통찰력을 가지므로 최적화가 가능합니다.
Generic 을 사용하지 않고 일반적으로 사용될 때는 힙 할당의 비용 발생하는 것을 알 수 있습니다.
런타임에 Type을 변경할 수 없습니다.
(Type does not change at runtime)
Pair Line을 만들면 실제로 Line 메모리는 enclosing pair 의 inline으로 할당됩니다.
(Storage inline)
추가 힙 할당이 필요하지 않습니다.
Struct Type 성능
struct type의 값을 복사 할 때 힙 할당이 필요하지 않습니다.
(No heap allocation on copying)
구조체에 참조가 포함되어 있지 않으면 참조 횟수가 없습니다.
(No reference counting)
정적 디스패치 기능을 통해 컴파일러 최적화와 런타임 (실행 시간)을 단축 할 수 있습니다.
(Static method dispatch)
Class Type 성능
힙 할당 및 인스턴스 생성
(Heap allocation on creating an instance)
참조 카운트 오버헤드
(Reference counting)
Virtual Table을 통한 동적 디스패치
(Dynamic method dispatch through V-Table)
Unspecialized Generics—Small Value