[WWDC 16 / Swift] Understanding Swift Performance with Reference Counting

박준혁 - Niro·2024년 5월 5일
1

WWDC

목록 보기
10/11
post-thumbnail

안녕하세요 Niro 🚗 입니다!

갈수록 Swift 를 깊게 알아야겠다는 생각이 들어 WWDC 16 에서 소개된
🔗 Understanding Swift Performance 를 보며 공부하고 정리를 해보고자 적게 되었습니다.

해당 영상에서 중심적으로 얘기하는 3가지의 주제가 있습니다.

  1. 인스턴스가 생성될 때 Stack 과 Heap 중 어디에 할당되는가?
  2. 인스턴스를 할당할 때 Reference Counting 이 발생하는가?
  3. 인스턴스에서 Method 를 호출할때 정적 or 동적 Dispatch 가 되는가?

이 중 2번째 편으로 '인스턴스를 할당할 때 Reference Counting 이 발생하는지?' 에 대해 알아보고자 합니다.

🔗 인스턴스가 생성될 때 Stack 과 Heap 중 어디에 할당되는가?

라는 첫번째 글을 읽고 오시면 더욱 이해가 잘 될거라 생각합니다.


1. 들어가기 앞서서...

첫번째 편에서 우리는 Struct 와 Class 의 동작에 대해 알아보았고 그 중 Heap 할당에 대해 자세히 알아보았습니다.

해당 내용을 설명할 때 reference Counting 에 대해서 언급을 했었는데

Swift 는 Heap 에 있는 모든 인스턴스에 대한 참조 개수를 유지 관리하기 때문에 안전하다고 합니다.

그럼 왜 reference counting 을 사용해야만 할까요?

reference counting 이 0 이라면 해당 인스턴스를 아무도 사용하지 않는다는 의미입니다. '굳이 메모리에 있을 필요없기 때문에 해제해도 되겠다' 라고 생각하면 좋을거 같습니다.

해당 영상에서 설명하기론 reference counting 작업은 매우 빈번하고 단지 숫자를 증감하는 것 이상의 작업이 필요하다고 합니다.

증감을 위해 간접 참조가 발생하게 되고 여러 스레드에서 동시에 해당 영역을 참조하거나 해제할 수 있기 때문에 굉장한 비용이 누적된다고 하네요!

자 그럼 어떻게 Reference counting 가 증감 되는지 차근 차근 알아보겠습니다.


2. Class 에서의 Reference Counting

Point 클래스로 인스턴스를 만들면 실제 데이터는 Heap 에 할당되고 해당 주소를 Stack 에 저장한다고 배웠습니다.

인스턴스가 만들어지게 되면 해당 영역을 참조하고 있다는 의미기 떄문에 reference counting 이 증가하게 되겠죠?

다음과 같이 Point Class 를 통해 point1 인스턴스를 만들었고 point2 에 할당했습니다. Heap 영역에 존재하는 refCount 가 2로 증가된 모습을 볼 수 있는 것처럼 해당 인스턴스가 얼마나 참조되고 있는지를 알 수 있습니다.

point1, point2 인스턴스를 사용하고 나서 반환하게 된다면 Heap 영역에 존재하는 데이터를 참조하지 않기 때문에 refCount 가 0 으로 바뀐 것을 볼 수 있습니다.

0 이 되는 순간 Swift 는 이제 해당 인스턴스를 아무도 사용하지 않는구나 라고 판단하여 Heap 영역에 접근하지 못하도록 lock 하고 해당 메모리 블럭을 반환하게 됩니다.


3. Struct 에서의 Reference Counting

Class 의 경우를 봤으니 Struct 도 살펴보겠습니다.

잠깐만.. Struct 는.. Heap 할당을 하지 않는데.. reference counting 이 발생..하나...?

라는 의문점을 가질 수 있습니다!

저도 궁금했고 당연히 발생하지 않을거라고 생각했는데 100% 인건 이 세상에 없는거 같습니다....

만약 Struct 내부에 참조 타입 프로퍼티가 존재한다면 어떻게 될까요?

struct Label {
	var text: String
	var font: UIFont
    
	func draw() { ... }
}

Label Struct 구조를 살펴보면 String 타입의 text 프로퍼티와 UIFont 타입의 font 프로퍼티가 있습니다.

앞서 1편에서 살펴본것 처럼 String 타입은 내용을 Heap 에 저장하기 때문에 reference counting 이 필요합니다.

UIKit 에서 사용하는 UIFont 타입은 Class 이기 때문에 당연히 reference counting 이 필요하죠!

Label 인스턴스를 생성하면 다음과 같은 메모리 구조를 갖게 됩니다. text, font 프로퍼티에 대한 참조가 발생하게 되고 인스턴스를 label2 에 복사했기 때문에 textfont 에 대한 reference counting 은 각각 2이고 해당 과정에서는 총 4번의 참조가 발생합니다.

여기서 retain 과 release 를 호출하여 Heap 할당을 추적할 수 있습니다.

결과적으로 Struct 는 참조하지 않지만 내부에 참조 유형의 프로퍼티를 갖고 있다면 reference counting 오버헤드를 처리하는 비용을 부담하게 됩니다.

즉, Class 를 사용했을 때 보다 두배를 부담하게 되는 셈이죠..

여기서 오버헤드(overhead) 란 어떠한 처리를 위해 필요한 시간, 메모리 등을 의미합니다.

자, 사용자가 이미지와 같은 첨부 파일을 서로 보내는 메세지 앱이 있다고 가정해봅시다.

Attachment 라는 Struct 는 디스크에 존재하는 데이터 경로를 저장하기 위한 fileURL 프로퍼티와 고유한 랜덤 식별자를 나타내기 위한 uuid 프로퍼티, 파일의 타입을 나타내는 mimeType 프로퍼티가 보이네요.

해당 Struct 를 초기화 할때 mimeType 중 지원하는 타입인지 확인하는 guard 구문도 보입니다.

init 파라미터에서 URL 타입은 struct 이지만 String 을 통해 초기화되기 때문에 참조가 발생하고 마찬가지로 uuidmimeType 은 String 타입이기 때문에 참조가 발생하게 됩니다.

3개 프로퍼티 모두 reference counting 오버헤드가 발생하게 되는 것이죠...

자, 그럼 우리가 해야할 일이 무엇인지 느낌이 오시나요?
Reference couting 오버헤드를 줄이는 방향으로 가야합니다!

URL 타입은.. 대체할 방법이 없기 때문에 그대로 사용하고 나머지 두 프로퍼티에 대해 바꿔보겠습니다.

움.. 16년도에 나온 영상이기 때문에 그 당시에는 새로운 기술이겠지만 우리는 지금 UUID 타입을 아무렇지 않게 잘 사용하고 있죠...?

기존에는 각 모델에 대한 고유성을 부여하기 위해 String 을 사용했지만 UUID 타입이 만들어졌고 Struct 로 구성되어 있기 때문에 참조가 줄어는 모습을 볼 수가 있습니다. (화살표 하나가 사라졌어요!)

UUID 유형은 고유한 식별자를 위해 만들어진 특별한 타입입니다!

다음은 mimeType 프로퍼티 입니다.
기존에는 여러 타입을 switch 구문을 통해 가능한지 판단하도록 만들었습니다.

이번에는 Swift 의 훌륭한 추상화 메커니즘인 Enum 으로 바꿔보겠습니다.

MimeType 이라는 enum 을 만들고 rawValue 값을 받아 해당하는 case 를 반환할 수 있도록 구현하여 유형 안전성을 확보할 수 있게 되었습니다.

기존에 String 유형이였던 uuidmimeType 프로퍼티를 UUIDEnumMumeType 유형으로 바꿔서 reference counting 오버헤드를 줄일 수 있게 되었습니다!

앞으로... model 을 만들 때 아무런 생각없이 유형을 선택하는 습관을 고쳐야겠다는 생각이 듭니다....


4. 정리해보자면

이번 글에서는 어떤 상황에서 reference counting 이 생기는가에 대해 알아보았습니다.

중요한 부분은 무조건 참조 유형인 Class 에서만 발생하는 것이 아니라
내부 프로퍼티 중에 참조 유형이 존재한다면

Struct 에서도 Reference counting 이 발생할 수 있다는 점입니다!

Reference counting 오버헤드를 줄이고자 우리는 String 유형을 enum 이나 UUID 유형으로 바꿔 reference counting 이 발생하지 않도록 성능 향상을 야기할 수 있었습니다.

모든 것에 항상 100% 라는건.. 없다는 것을 다시 깨달으며 다음 글도 얼른 준비해보겠습니다!

이번 글도 읽어주셔서 감사하고 피드백은 환영입니다!

profile
📱iOS Developer, 🍎 Apple Developer Academy @ POSTECH 1st, 💻 DO SOPT 33th iOS Part

0개의 댓글

관련 채용 정보