V8 엔진 블로그에 2019년 1월 3일에 작성된 글 바탕으로 조사하여 작성된 글입니다.
Link : https://v8.dev/blog/trash-talk
Garbage Collector(GC) VS Garbage Collection
들어가기 앞서 Garbage Collector 과 Garbage Collection의 차이점을 알고 들어가는 것이 좋을 것같아 두개의 차이점을 간단히 작성한다.
Garbage Collector(GC)
GC는 프로그래밍 언어의 런타임 환경에서 메모리 관리를 담당하는 모듈이나 구성 요소를 의미한다.
프로그램이 더 이상 사용하지 않는 객체를 자동으로 찾아서 메모리에서 제거하는 역할을 담당하며, 다음과 같은 작업을 수행한다.
- 객체 추적 : 메모리에 할당된 객체들을 추적
- 참조 카운트 관리 : 객체에 대한 참조가 없어지면 해당 객체가 사용되지 않는 것으로 판별
- 메모리 회수 : 사용되지 않는 객체를 메모리에서 제거하여 메모리 누수를 방지
- 힙 관리 : 메모리 힙을 효율적으로 관리하여 프로그램 성능을 최적화
Garbage Collection
Garbage Collection은 GC가 수행하는 과정 또는 메커니즘을 의미한다.
메모리 관리를 위해 수행되는 일련 단계들을 포함하며, 주요 단계는 다음과 같이 요약이 가능하다.
좀더 자세한 내용은 아래에서 다룰 예정이다.
- Marking (마킹) : 현재 사용 중인 객체와 사용되지 않는 객체를 구분, 이 단계에서는 모든 객체를 순회하면서 접근 가능한 객채인지 마킹한다.
- Sweeping (스위핑) : 마킹되지 않은, 즉 접근이 되지 않는(사용되지 않는) 객체를 메모리에서 제거
- Compaction (압축) : 메모리 단편화를 줄이기 위해 객체를 연속된 메모리 블록으로 이동
- Copying (복사) : 객체를 복사하여 새로운 공간에 재배치함으로써 사용 중인 객체만 남기고 나머지 공간을 정리
요약
Gabage Collector(GC)는 메모리 관리를 담당하는 런타임 시스템의 모듈을 의미하며,
Gabage Collection은 GC가 수행하는 메모리 관리 과정을 의미한다.
V8 GC
Major GC (Full Mark-Comapct)
V8 GC의 Major GC는 힙 전체에서 Garbage Collection을 수행 한다.
이때 Marking, Sweeping, Compact 의 3개의 과정을 수행한다.
Marking
GC의 필수적인 기능이며, 객체를 수집해야 하는지 체크하는 단계
Liveness를 파악하는 단계이며, Liveness는 객체가 여전히 프로그램에 접근이 가능한 상태인지를 나타낸다.
런타임 내에 접근 가능한 객체는 모두 유지가 되고, 접근이 불가능한 객체를 수집한다.
Marking 단계는 다음과 같이 진행 된다.
- 루트 집합 식별 (Identify Root Set): 루트 집합은 실행 스택, 전역 변수, 레지스터 등 프로그램에서 직접 참조되는 객체들입니다. 이 루트 집합으로부터 시작하여 객체의 Liveness를 추적
- 객체 방문 (Traverse Objects): 루트 집합에 포함된 각 객체를 시작점으로 하여 해당 객체가 참조하는 다른 객체들을 재귀적으로 방문합니다. 이 과정을 통해 접근 가능한 모든 객체를 탐색
- 마킹 (Marking): 방문한 각 객체를 "마크"하여 접근 가능함을 표시합니다. 마킹된 객체는 Liveness가 있는 것으로 간주되며, 이를 통해 어떤 객체가 여전히 사용 중인지 확인할 수 있다
Sweeping
앞서 Marking 단계에서 마킹되지 않은 객체들을 메모리 할당을 해제한다. 이후 사용중인 메모리 사이에 해제된 메모리 틈(gaps)에 Free List를 추가하는 단계이다.
Sweeping 단계는 다음과 같이 진행 된다.
- 마킹되지 않은 객체 식별 (Identify Unmarked Objects): Marking 단계에서 마킹되지 않은, 즉 사용되지 않는 객체들을 식별
- 메모리 해제 (Memory Deallocation): 식별된 객체를 메모리에서 해제하여 메모리 풀이 다시 사용할 수 있도록 한다..
- 프리 리스트 관리 (Free List Management): 해제된 메모리 블록을 프리 리스트(Free List)에 추가한다. 프리 리스트는 사용 가능한 메모리 블록의 목록을 유지하여 새로운 메모리 할당 요청 시 빠르게 사용될 수 있도록 한다.
Compaction
메모리 단편화를 줄이고 사용가능한 메모리 블록을 연속된 공간으로 만드는 작업이다. Heap을 압축하는 단계라 생각하면 된다.
V8 엔진은 Generational Garbage Collection 방식을 사용하며 주로 Mark-Compact 알고리즘을 통해 Compaction을 수행한다.
이는 과거 윈도우 PC의 조각 모음이라 생각하면 된다.
살아 있는 데이터를 빈 공간을 모두 찾아 복사 붙여넣기 형식으로 압축을 하게 되면 상당히 많은 비용이든다. 이에 매우 단편화된 페이지들만 선택적으로 압축을 진행한다.
이때 페이지는 힙 메모리의 일부를 의미하며, 단편화된 페이지는 빈 공간이 많은 메모리 페이지를 의미한다.
덜 단편화된 페이지는 Sweeping을 진행하고, 단펴화된 페이지는 Compaction을 진행하여 효율적으로 메모리를 관리한다.
Compaction 단계는 다음과 같은 과정을 실행한다.
- Marking Phase: GC 루트 집합으로부터 시작하여 모든 살아있는 객체를 탐색하고 마킹
- Compute Forwarding Addresses: 각 살아있는 객체가 이동할 새 위치를 계산, 이는 메모리 블록을 압축하는 데 필요한 정보를 제공한다.
- Update References: 모든 객체의 참조를 업데이트하여 새 위치를 가리키도록 한다. 이는 Compaction 과정에서 가장 복잡한 부분 중 하나로, 모든 참조가 올바르게 유지될수 있게 위치를 가르킨다.
- Move Objects: 살아있는 객체를 새로운 위치로 이동, 이동 과정에서 비어 있는 공간을 하나의 큰 연속된 블록으로 만든다.
- Free Space Management: 이동이 완료된 후, 통합된 자유 메모리 블록을 Free List에 추가하여, 다음 메모리 할당 요청 시 사용할 수 있도록 합니다.
'CS' 카테고리의 다른 글
[ Web ] V8 - #01 Javascript Engine (0) | 2024.05.04 |
---|---|
WebSocket Protocol (0) | 2024.04.25 |