힙 메모리 영역은 동적할당을 한다.
–> 사용하지 않은 메모리를 찾아 동적으로 할당한다.
–> thread safety를 보장하기 위해 비교적 성능이 떨어질 수 밖에 없다.
따라서 힙 메모리 영역이 스텍 메모리 영역보다 성능이 떨어진다.
String의 경우도 힙 영역을 사용한다.
String의 경우 얼마나 긴 값이 할당될 지 모르기 때문에(=크기가 정해져 있지 않기 때문에) 힙 영역에 저장된다.
Dictionary, Array, Set
의 값도 위와 같은 이유로 힙 영역을 사용한다.
-> struct로 구현한다고 하더라도 힙 영역에 메모리를 저장한다.
클래스 타입의 인스턴스에만 적용되고 값 타입인 구조체, 열거형 등에는 적용되지 않는다.
스택 영역에서 힙 영역을 가리키는 갯수를 말한다.
ARC
(Auto Refernce Counting)가 카운트를 올려주고 내려준다.
힙 영역을 사용하는 구조체
struct Point {
let name: String
let clothes: [String]
}
구조체의 프로퍼티로 String, Array(=힙 영역을 사용하는) 타입을 갖게 되면 참조가 발생한다.
스택에는 String, UIFont의 힙 영역 주소값이 저장된다.
구조체가 복사되거나 해제되면 프로퍼티마다 RC를 올리고 내리는 작업이 수행된다.
힙 영역을 사용하는 구조체는 클래스를 사용할 때 보다 성능이 오히려 안좋은 경우가 있다.
-> 값 타입을 갖는(=스택 영역만 사용하는) 코드를 지향하는 것이 좋다. 그러지 못할 경우 클래스를 사용하는 것이 좋을 경우가 있다.
Swift가 컴파일 시간에 실행할 메소드를 말할 수 있다면 이를 정적 디스패치라고 하며 런타임에 해당 코드로 바로 이동할 수 있다.
동적 디스패치
의 경우 메서드의 위치가 다르므로, 사용할 때 메서드를 찾는 과정이 필요하다.
-> 정적 디스패치
를 사용하는 방식을 지향하여 최적화 가능성을 높인다.
inline
방식: 호출되는 위치에 함수 본문을 문자 그대로 복사하여 붙여넣어서 실행 -> 최적화
컴파일러는 인라인 또는 기타 트릭을 통해 주변 코드에 적극적으로 최적화할 수 있다.
그렇지 않으면 코드에 도달하기 전에 오버헤드가 있는 동적 디스패치를 사용하고 주요 단점인 컴파일러 최적화를 포기한다.
상속 기반 다형성은 코드에서 더 많은 유연성을 제공하지만 정적 디스패칭을 포기한다.
final 클래스로 상속을 제한하면 무조건 해당 클래스만 들어오기에 인라인 방식이 가능해진다.
? 무조건적으로 Static Dispatch가 유리하다면 Dynamic Dispatch는 왜 존재할까 ?
메모리 할당 측면에서 힙은 동적으로 할당하기 때문에 오버헤드가 발생할 수 있어서 스택 영역이 더 좋은 성능을 가짐