ARC/GC

지니🧸·2023년 4월 3일
0

Swift

목록 보기
1/4
post-thumbnail

다른 언어에서는 주로 GC 사용

Garbage Collection

Garbage: 유효하지 않은 메모리

  • C에서는 free() 함수로 직접 메모리 해제해야 함
  • Java에서는 JVM의 garbage collector가 불필요한 메모리를 알아서 정리해줌
    • 명시적으로는 null 선언 가능

Minor & Major Garbage Collector

  • 객체는 대부분 일회성되며, 메모리에 오랫동안 남아있는 경우는 드뭄
  • 객체의 생존 기간에 따라 물리적 Heap 영역을 Young, Old으로 나뉨
    • Young 영역, Young generation
      • 새롭게 생성된 객체가 할당되는 영역
      • 대부분의 객체가 금방 unreachable 상태가 되기 때문에 많은 객체가 Young 영역에 생성되었다가 사라짐
      • Young 영역에 대한 garbage collection > Minor Collection
    • Old 영역, Old Generation
      • Young 영역에서 reachable 상태를 유지하여 살아남은 객체가 복사되는 영역
      • Young 영역보다 크게 할당됨
      • 영역의 크기가 큰만큼 garbage는 적게 발생
      • Old 영역에 대한 garbage collection > Major Garbage Collection
  • Old 영역이 Young 영역보다 크게 할당되는 이유: Young 영역의 수명이 짧은 객체들은 큰 공간을 필요로 하지 않으며 큰 객체들은 Young 영역이 아니라 바로 Old 영역에 할당

Garbage Collection의 동작 방식

1. Stop The World: JVM이 애플리케이션의 실행을 멈추는 작업

  • GC가 실행될 때는 GC를 실행하는 스레드를 제외한 모든 스레드들의 작업이 중단
    • GC가 완료되면 작업 재개

2. Mark and Sweep

  • Mark: 사용되는 메모리와 사용되지 않는 메모리 식별 작업

  • Sweep: Mark 단계에서 사용되지 않음으로 식별된 메모리 해제 작업

  • Stop The World을 통해 모든 작업을 중단시키면 Garbage Collector는 스택의 모든 변수 또는 reachable 객체를 스캔하면서 각각이 어떤 객체를 참고하고 있는지를 탐색

  • Mark에서 사용 메모리 식별

  • Mark되지 않은 객체를 메모리에서 제거

Minor GC의 동작 방식

Young 영역은 1개의 Eden 영역과 2개의 Survivor 영역, 총 3가지로 나뉨

  • Eden 영역: 새로 생성된 객체가 할당되는 영역
  • Survivor 영역: 최소 1번의 GC 이상 살아남은 객체가 존재하는 영역

객체가 새롭게 생성되면 Young 영역의 Eden 영역에 할당됨

  • Eden 영역이 꽉 차면 Minor GC 발생
    • 사용되지 않는 메모리 해제
    • Eden 영역에 존재하는 사용중인 객체는 Survivor 영역으로 이동
      • Survivor 영역은 총 2개지만 반드시 1개의 영역에만 데이터가 존재해야 함
  1. 새로 생성된 객체가 Eden 영역에 할당됨
  2. 객체가 계속 생성되어 Eden 영역이 꽉 차게 되고 Minor GC가 실행됨
  3. Eden 영역에서 사용되지 않는 객체의 메모리가 해제
  4. Eden 영역에서 살아남은 객체는 1개의 Survivor 영역으로 이동됨
  5. 1~2번의 과정이 반복되다가 Survivor 영역이 가득차게 되면 Survivor 영역의 살아남은 객체를 다른 Survivor 영역으로 이동시킴 > 1개의 Survivor 영역은 반드시 빈 상태가 됨
  6. 이러한 과정을 반복하여 계속해서 살아남은 객체는 Old 영역으로 이동(Promotion)됨

객체의 생존 횟수를 카운트하기 위해 Minor GC에서 객체가 살아남은 횟수를 의미하는 age를 Object Header에 기록

  • Minor GC 때 Object Header에 기록된 age를 보고 Promotion 여부 결정
  • Survivor 영역 중 1개만 반드시 사용되어야 함
    • 만약 두 Survivor 영역에 모두 데이터가 존재하거나, 모두 사용량이 0이라면 현재 시스템이 정상 상황이 아님을 알 수 있음

Major GC 동작 방식

  • Young 영역에서 오래 살아남은 객체는 Old 영역으로 Promotion됨
  • Major GC: 객체들이 계속 promotion 되어 Old 영역의 메모리가 부족해짐
  • Young 영역은 일반적으로 Old 영역보다 크기가 작기 때문에 GC가 보통 0.5초~1초 내에 끝남
    • Minor GC는 애플리케이션에 큰 영향 주지 않음
  • Old 영역은 Young 영역보다 큼 & Young 영역을 참조할 수 있음
    • Major GC는 Minor GC보다 오래 걸리며 10배 이상의 시간 사용

Automatic Reference Counting

Automatic Reference Counting:

  • Swift가 앱의 메모리 사용을 추적/관리 하는 방식
  • 주로 프로그래머가 관리할 필요 없이 자동으로 더이상 필요없는 인스턴스가 사용하던 메모리를 해제함
  • 오직 클래스 인스턴스만 관리
    • struct/enum은 대상 아님

ARC 작동 방식

  • 새로운 클래스 인스턴스를 생성할 때마다 ARC는 인스턴스 정보를 저장할 수 있도록 메모리 공간을 할당함
    • 이 인스턴스 정보에는 인스턴스 종류와 저장된 값 등이 들어감
  • 인스턴스가 더이상 필요 없어지면 다른 목적으로 쓰일 수 있도록 인스턴스에 할당된 메모리를 해제함: 쓸데없는 인스턴스가 메모리를 차지하지 않도록
  • ARC가 사용 중인 인스턴스의 메모리를 해제하면 인스턴스의 속성과 메서드를 호출할 수 없게됨 > 앱의 비정상 종료 가능성 존재
  • 인스턴스가 아직 필요할 동안 사라지지 않도록 ARC는 각 클래스 인스턴스를 참조하는 속성, 상수, 변수의 수를 추적함
    • 현재 1개 이상의 참조가 존재하는 클래스 인스턴스는 해제되지 않음
  • 클래스 인스턴스를 속성/상수/변수에 배정하면 이 속성/상수/변수가 인스턴스에 강한 참조(Strong reference)를 한다
    • 참조하는 속성/상수/변수가 존재하는 동안에는 클래스 인스턴스가 해제될 수 없기 때문에 강하게 붙잡고 있는다 하여 강한 참조라 불림

Strong Reference Cycle

Strong Reference Cycle: 두 클래스 인스턴스가 서로에 대해 강한 참조일 때 각 인스턴스가 다른 인스턴스를 살아남게 함

Weak/unowned 참조를 통해 해결 가능: 순환 참조의 인스턴스가 강한 참조 없이 순환 내의 상대 인스턴스를 참조할 수 있도록

  • Weak 참조:
    • 상대 인스턴스가 더 짧은 수명을 가질 때 사용
      • 상대 인스턴스가 더 빨리 해제
  • Unowned 참조:
    • 상대 인스턴스가 본인 이상의 수명을 가질 때

Weak 참조

강한 참조가 아니기 때문에 ARC가 해제하는 것을 막지 못함

  • weak 참조 중에 해제 가능 > 참조 중일 때 해제되면 런타임에 값을 nil로 설정
    속성/변수 선언 전에 weak 키워드 사용. 항상 값은 optional

Unowned 참조

속성/변수 선언 전에 unowned 키워드 사용
unowned 참조는 항상 값이 존재.

Unowned Optional 참조: Weak 참조와 같이 사용 가능


참고:

profile
우당탕탕

0개의 댓글

관련 채용 정보