[C#] 가비지 컬렉터

JUYEONG·2023년 10월 16일
0

C#

목록 보기
2/2

가비지 컬렉터란?

  • GC(Garbage Collector)는 자동 메모리 관리자 역할로 애플리케이션의 메모리를 할당 및 해제 역할을 한다.
  • 개발자가 직접 메모리 관리 작업을 위한 코드를 작성할 필요가 없다.
  • 메모리 누수, 해제된 메모리에 접근과 같은 문제를 방지한다.

이점

  • 개발자가 수동으로 메모리 해제할 필요가 없다.
  • 관리되는 힙 메모리에 효율적으로 개체를 할당한다.
  • 더 이상 사용되지 않는 개체를 회수하고 메모리를 비워 이후 할당에서 해당 메모리를 사용할 수 있게 한다.
  • 관리되는 개체는 자동으로 시작을 위한 정리된 컨텐츠를 받으므로 개체의 생성자가 모든 데이터 필드를 초기화하지 않아도 된다.
  • 개체가 다른 개체에 할당된 메모리 주소에 접근할 수 없도록 하여 메모리 보안을 제공한다.

메모리 기본 사항

  • 각 프로세스에는 고유한 개별 가상 주소 공간이 있다.
  • 기본적으로 32비트 컴퓨터에서는 각 프로세스에 2GB 사용자 모드 가상 주소 공간이 포함된다.
  • 개발자는 가상 주소 공간만 이용하고 가비지 컬렉터가 관리되는 힙에서 개발자 대신 가상 메모리 할당 및 해제를 한다.
  • 가상 메모리는 다음 세 가지 상태일 수 있다.

    1) Free : 메모리 블록에 가상 메모리에 대한 참조가 없으며 해당 메모리 사용 가능
    2) Reserved : 메모리 블록은 사용 가능하지만 다른 할당 요청에 사용할 수 없다. 그러나 커밋될 때까지 데이터를 저장할 수 없다.
    3) Committed : 메모리 블록이 실제 스토리지에 할당되어 있는 상태.

  • 가상 주소 공간은 조각화 될 수 있다.

    1) 메모리 할당을 요청하면 할당 받은 메모리를 충족할 만큼 충분한 단일 메모리 블록이 필요하다.
    2) 그림과 같이 메모리 사이에 비어있는 공간이 있을 수 있다.
    3) 전체 여유공간이 아닌 할당 가능한 단일 메모리 블록보다 큰 메모리를 할당하려고 하면 실패할 수 있다.

가비지 수집 조건

  • 시스템의 메모리가 부족할 경우 -> 운영체제의 메모리 부족 알림 또는 낮은 메모리에 의해 검색
  • 관리되는 힙의 할당된 개체에 사용되는 메모리가 임계값을 초과할 때. *임계값은 프로세스가 실행됨에 따라 수시로 조정됨.
  • 수집될 때 GC.Collect 메서드가 호출된다. *명시적으로 호출 가능

관리되는 힙 (Managed Heap)

  • 가비지 컬렉터가 관리하는 메모리

  • 관리되는 각 프로세스 별로 관리되는 힙이 존재한다.

  • 프로세스의 모든 스레드는 관리되는 힙을 공유한다.

  • GC 알고리즘은 다음과 같은 세 가지를 기반으로 한다.

    1) 메모리 파편화 방지를 위해 메모리를 압축한다.

    2) 최근에 만들어진 개체일수록 수명이 짧고, 오래될수록 수명이 길어 재사용할 메모리를 빠르게 분류할 수 있다.

    3) 메모리 할당은 0세대에서만 일어난다. 최근에 만들어진 개체일 수록 서로 연관되는 경향이 있어 서로 빠르게 접근하는데 용이하다.

  • 관리되는 힙은 0세대, 1세대, 2세대로 나눠져 있다.

    1) 0세대 : 수명이 짧은 개체. 새로 할당된 개체. 다만, 85KB 이상의 용량이 큰 개체일 경우 2세대 LOH(Large Obejct Heap)로 이동한다.

    2) 1세대 : 수명이 짧은 개체를 포함하며 0세대와 2세대 사이의 버퍼역할을 한다.

    3) 2세대 : 수명이 긴 개체.

메모리 할당

  • 모든 참조 타입 개체는 매니지드 힙의 0세대에 할당된다.
  • 주소 공간을 사용할 수 있는 한 바로 다음에 주소 공간에 메모리를 할당합니다.
  • 85KB 이상의 크기를 가지는 개체는 LOH(Large Object Heap)라는 2세대 메모리에 할당된다.

메모리 해제

  • 수행 중인 할당에 따라 수집을 수행하기에 가장 적합한 시간을 결정한다.
  • 세대별 가비지 컬렉터는 추적 가비지 컬렉션을 사용한다.
  • 애플리케이션의 루트를 검사하여 더 이상 사용되지 않는 개체를 결정한다.
  • 유지 및 승격

    1) 0세대 가비지 수집에서 남은 개체는 1세대로 승격.
    2) 1세대 가비지 수집에서 남은 개체는 2세대로 승격.
    3) 2세대 가비지 수집에서 남은 개체는 2세대로 유지.

가비지 컬렉션 수행 과정

1) 모든 활성 개체를 찾아 목록을 만드는 표시 단계
2) 압축될 개체에 대한 참조를 업데이트하는 재배치 단계
3) 비활성 개체에 의해 점유된 공간을 회수하고 남은 개체를 압축하는 압축단계. * 살아남은 개체를 세그먼트의 끝으로 이동시킨다.

가비지 수집에 필요한 정보

  • 스택 루트 : JIT (Just In Time) 컴파일러 및 스택 워커에서 제공하는 스택 변수
  • 가비지 수집 핸들 : 관리되는 개체를 가리키고 사용자 코드 또는 CLR에서 할당할 수 있는 핸들
  • 정적 데이터 : 다른 개체를 참조할 수 있는 애플리케이션 도메인의 정적 개체.

가비지 판단

  • 추적 가비지 수집(Tracing Garbage Collection)

도달 가능성(Reachability)로 생존을 가정하는데 루트를 사용하여 해당 메모리에 도달할 수 있는지를 판단한다.

  • 참조 카운팅(Reference Counting)

해당 메모리에 참조하는 것이 없을 때 가비지로 가정한다. 이때, 순환 참조를 조심해야 하는데 이를 방지하기 위해 약한 참조라는 개념이 사용된다.

주의할 점

  • 가비지 컬렉션은 가벼운 연산이 아니므로 성능을 위해서 주의해야한다.

  • 멀티스레드 환경에서 GC가 수행됨에 따라 다른 스레드가 중지된다.

  • 다음와 같은 경우를 주의하자.

    1) 빈번한 개체 생성 : 개체의 빈번한 생성으로 인한 메모리 부족은 GC가 일어나는 조건 중 하나이므로 주의하자.
    2) 너무 큰 개체 생성 : 85KB 이상의 개체를 생성하면 LOH에 할당되고 메모리 압축이 일어나지 않기 때문에 주의하자.
    3) 관리되지 않은 리소스에 대한 관리 : 파일 핸들, 창 핸들 또는 네트워크 연결 등의 운영 체제 리소스를 래핑하는 개체는 GC의 관리 대상이 아니므로 Dispose, using문 등을 활용해 관리하자.

출처 : Microsoft Docs, Blog
https://learn.microsoft.com/ko-kr/dotnet/standard/garbage-collection/fundamentals
https://haedallog.tistory.com/188

0개의 댓글

관련 채용 정보