Swift: Automatic Reference Counting / ARC / 자동 참조 계수

Wooyo·2023년 10월 25일
0

Swift / 메모리관리

목록 보기
1/2
post-thumbnail

참고 사이트 : https://babbab2.tistory.com/26

1. 메모리 관리

  • swift의 메모리 관리의 핵심은 힙 영역 관리가 핵심
  • 참조 타입은 자동으로 힙에 할당
  • 참조 타입 : Instance, Class type, String(일부)
  • 힙 영역 관리 -> 사용하고 난 후에는 반드시 메모리 해제를 해줄 것
  • 다음과 같은 예
class Human {
	var name: String?
    
    init(name: String) {
    	self.name = name
    }
}

let jimin = Human(name: "Jimin")

// 지역 변수 jimin은 stack 영역 이지만 Human instance의 경우 heap 영역

let minjung = jimin

// 인스턴스는 복사 되지 않고 heap 영역의 Human은 한 개만이 존재

// minjung, jimin이 사라지고 난 후에도 Human instance는 계속 존재
  • 힙에 남은 인스턴스가 계속 존재하게 되는데 이 메모리를 해제해주는 것이 ARC (Automatic Reference Counting)

2. Automatic Reference Counting

  • 클래스 인스턴스가 더 이상 필요하지 않을 때 메모리를 자동으로 해제하는 기능
  • 즉, 힙에 할당된 인스턴스 메모리를 관리해주는 기능

3. Reference Counting

  • 힙 영역의 메모리를 관리하는 방법
  • 자바의 Garbage Collection과 비교
  • 가장 큰 차이점은 참조를 계산하는 시점
  • Garbage Collection
참조계산 시점: 
- Runtime 
- 앱 실행 동안 주기적으로 잠조를 추적, 사용하지 않는 instance를 해제

장점: 인스턴스가 해제될 확률이 높음

단점: 
- 개발자가 참조 해제 시점을 파악할 수 없음
- Runtime 시점에 계속 추적하는 추가 리소스 필요로 성능저하 발생 가능성 존재
  • Reference Counting
참조계산 시점:
- 컴파일 시점에 참조되고 해제되는지 결정되어 런타임 시 그대로 실행

장점: 
- 개발자가 참조 해제 시점을 파악할 수 있음
- Runtime 시점에 추가 리소스가 발생하지 않음

단점:
- 순환 참조가 발생 시 영구적 메모리 해제가 되지 않을 수 있음

3. ARC의 메모리 관리 방법

  • 메모리 참조 횟수를 계산하여 참조 횟수가 0이되면 더 이상 사용하지 않은 메모리라 생각하여 해제
  • 이 인스턴스를 현제 누가 가르키고 참조 여부를 숫자로 나타낸 것이 RC

4. Reference Count가 올라가는 경우

  • 인스턴스를 새로 생성하는 경우
  • 기존 인스턴스를 다른 변수에 대입하는 경우

5. Reference Count가 내려가는 경우

  • 인스턴스를 가르키던 변수가 메모리에서 해제되는 경우
func makeClone(origin: Human) {
	let clone = origin
    //2. RC: 2 (jimin을 참조하는 clone 변수 생성 순간 + 1)
}

let jimin = Human(name: "jimin")
// 1. RC: 1 (인스턴스 생성 순간 + 1)
makeClone(jimin)
// 3. RC: 1 (clone 이 스택에서 해제되는 순간 - 1)
  • nil이 지정되는 경우
var jimin: Human? = Human(name: "Jimin") // 1. RC: 1
var clone = jimin // 2. RC: 2

clone = nil // 3. RC: 1
jimin = nil // 4. RC: 0
  • 변수에 다른 값을 대입한 경우
var jimin: Human? = Human(name: "Jimin") // jimin RC : 1
var minjung: Human? = Human(name: "Minjung") // minjung RC : 1

jimin = minjung // minjung RC : 2 , jimin RC : 0
  • 프로퍼티의 경우 속해 있는 클래스 인스턴스가 메모리에서 해제되는 경우
class Contact {
	var email: String?
    
    init(email: String) {
    	self.email = email
    }
}

class Human {
	var name: String?
    // Human class 속 Contact 클래스 인스턴스가 프로퍼티로 존재
    var contact: Contact? = Contact(email: "jimin@naver.com")
    
    init(name: String) {
    	self.name = name
    }
}

let jimin: Human = .init(name: "Jimin") // Human RC: 1, Contact RC: 1, total RC : 2
jimin = nil 
// nil 할당 순간 Human RC: 0
// Human Instance가 메모리에서 해제되면서 Contact Instance RC 감소
profile
Wooyo의 개발 블로그

0개의 댓글