코린이의 개발 일지

[JavaScript] 가비지 컬렉션 (Garbage Collection) 본문

자바스크립트

[JavaScript] 가비지 컬렉션 (Garbage Collection)

폴라민 2023. 2. 10. 15:00
반응형

가비지 컬렉션

  • 자바스크립트 엔진 내에서는 가비지 컬렉터가 끊임없이 동작한다.
  • 가비지 컬렉션은 자바스크립트 엔진이 자동으로 수행하므로 개발자는 이를 억지로 실행하거나 막을 수 없다.

 

가비지 컬렉션 기준

도달 가능성(reachability)

  • 도달 가능한 값은 어떻게든 접근하거나 사용할 수 있는 값을 의미한다.
  • 참조 된다고 해서 도달 가능한 것은 아니다. 서로 연결된 객체들도 도달 불가능할 수 있다. ⇒ 루트에서 체이닝으로 도달 가능해야 한다.

도달 가능한 값

  • 루트(root)
    • 현재 함수의 지역 변수와 매개변수
    • 중첩 함수의 체인에 있는 함수에서 사용되는 변수와 매개변수
    • 전역 변수
    • 기타 등등
  • 루트가 참조하는 값, 혹은 체이닝으로 루트에서 참조할 수 있는 값
  • 이때 외부로 나가는 참조는 도달 가능한 상태에 영향을 주지 않는다. 외부에서 들어오는 참조만이 도달 가능한 상태에 영향을 준다.

예시

// user엔 객체 참조 값이 저장됩니다.
let user = {
  name: "John"
};

  • 이때 user를 다른 값으로 덮어 버리면 John은 도달할 수 없는 상태가 되어, 삭제된다.
user = null;

 

 

두개의 변수가 같은객체를 가리킬 때

  • 만약 두개의 변수가 같은 객체를 가리킬때,
// user엔 객체 참조 값이 저장됩니다.
let user = {
  name: "John"
};

let admin = user;
  • user를 다른 값으로 덮어도 여전히 admin 변수를 통해 접근 가능하기 때문에 John은 삭제 되지 않는다.
user = null;

 

 

외부로 나가는 참조만 있을 때

아래와 같은 상황은 어떨까?

  • 외부로 나가는 참조는 도달 가능한 상태에 영향을 주지 않는다. 외부에서 들어오는 참조만이 도달 가능한 상태에 영향을 준다.
  • 따라서 John에 저장된 데이터는 외부로 나가는 참조만 있고, 외부에서 들어오는 참조가 없기 때문에 삭제된다.

 

가비지 컬렉터 내부 알고리즘

mark-and-sweep

  • 가비지 컬렉션 기본 알고리즘

 

가비지 컬렉션 단계

  • 가비지 컬렉터는 루트(root) 정보를 수집하고 이를 ‘mark(기억)’ 한다.
  • 루트가 참조하고 있는 모든 객체를 방문하고 이것들을 ‘mark’ 한다.
  • mark 된 모든 객체에 방문하고 그 객체들이 참조하는 객체도 mark 한다. 한번 방문한 객체는 전부 mark 하기 때문에 같은 객체를 다시 방문하는 일은 없다
  • 루트에서 도달 가능한 모든 객체를 방문할 때까지 위 과정을 반복한다.
  • mark 되지 않은 모든 객체를 메모리에서 삭제한다.
  • 아래 그림을 보면 루트가 참조하고 있는 객체부터 모두 방문하고 한단계씩 depth를 내려가면서(BFS 방식) mark하고 mark되지 않은 모든 객체를 삭제한다.

기본적인 동작은 마킹 → 마킹되지 않은 객체 삭제 이다.

이제 좀더 구체적으로 가비지 컬렉터의 동작 방식을 살펴보자.

 

메모리 구조(v8 엔진)

힙 영역은 세부적으로 New Space, Old Space, Large Object space, 코드 space, 셀 space, 속성 space, 맵 space로 이루어져 있다.

가비지 컬렉션이 일어나는 부분은 New space와 Old space이므로 이번에는 두 space에 대해서만 알아보자.

  • New Space : 새로 만들어진 Object가 저장된다.
  • Old Space: New space에서 마이너 가비지 컬렛션이 2번 발생할 동안 살아남은 객체들이 저장된다. 이 영역은 두개로 나눌 수 있다.
    • Pointer space: 다른 객체를 참조하는 객체, 즉 다른 개체에 대한 포인터를 가진 객체
    • Data space: 문자열, 실수 등의 데이터만을 가진 객체

그럼 GC의 동작방식을 살펴보자

New Space

  • 마이너 GC로 관리하는 영역이다.
  • 마이너 GC는 객체들의 생명 주기가 짧은 New space에서 빠르게 가비지 컬렉션을 한다.
  • Semi space 두개로 나뉘어져 있으며 마이너 GC는 다음과 같이 동작한다.

마이너 GC 동작

  • Semi space는 하나는 비어있는 To space, 하나는 객체들이 머무르는 From space이다.
  • 마이너 GC가 한번 동작하고 살아남은 객체들은 From space에서 To space로 이동한다.
  • 이동할 때, 살아남은 객체들은 연속적으로 이동한다.
    • 메모리 단편화를 주기적으로 방지해주는 장점이 있다.

  • From space에서 To space로 생존한 객체들의 이동이 완료되면 From space에 남아있는 쓸모없는 객체를 버린다.
  • From space와 To space의 역할을 서로 바꾼다.

  • 그리고 이후에 또 마이너 GC가 동작할 때, 새로 할당된 객체는 To space로 이동하지만, 기존에 한번 생존했던 4개의 객체는 또한번 생존할 경우 Old space로 이동한다.

Old space

  • 메이저 GC로 관리하는 영역이다.
  • 메이저 GC는 메모리 사이즈가 큰 Old space에서 가비지 컬렉션을 한다.
  • Pointer space랑 Data space 두가지 영역으로 나뉘어 있다.
  • 이곳에서 앞서 언급했던 Mark-Sweep-Compact 알고리즘과 Tri-color 알고리즘을 사용하여 가비지 컬렉션을 진행한다.

메이저 GC 동작

  • 크게 세가지 단계를 거치는데, 마킹 → 스위핑 → 압축 이다.
  • 마킹은 앞서 살펴본 방식이다. 루트부터 시작해서 체이닝으로 도달할 수 있는 깊이까지 dfs로 탐색하여 마킹
  • 스위핑은 참조 불가능한 객체 (마킹이 안된 부분)들의 메모리 주소를 free-list라는 자료구조에 추가하는 작업이다. 이 곳에 추가된 메모리 공간은 새로운 객체 저장가능한 주소들이다.
  • 압축은 메모리 단편화가 심한 페이지들을 재배치하여 추가적인 메모리를 확보하는 작업이다.

 

 

 

 

 

Refs.

https://ko.javascript.info/garbage-collection

 

가비지 컬렉션

 

ko.javascript.info

https://fe-developers.kakaoent.com/2022/220519-garbage-collection/

 

자바스크립트 v8 엔진의 가비지 컬렉션 동작 방식

카카오엔터테인먼트 FE 기술블로그

fe-developers.kakaoent.com

 

반응형
Comments