[모던자바스크립트] 24. 가비지 컬렉션


이 글은 번역 및 정리 글입니다. 출처: javascript.info

가비지 컬렉션

자바스크립트의 메모리 관리는 잘 보이지 않는다. 우리는 많은 변수, 객체, 함수등을 만든다. 더 이상 필요하지 않을경우는 어떻게 되는가? 자바스크립트엔진이 어떻게 그것을 발견하고 정리하는가?

접근성

자바스크립트에서 메모리 관리의 핵심 개념은 접근성이다.

간단히 말해, 도달 가능한 값은 어떻게든 액세스하거나 사용할 수 있는 값이다. 이러한 도달 가능한 값들은 메모리에 저장되도록 보장된다.

도달 가능한 값의 기본 집합이 있다.

  • 현재 기능의 지역 변수 및 매개 변수
  • 현재 중첩 호출 체인의 다른 함수에 대한 변수 및 매개 변수
  • 글로벌 변수
  • (…다른 내부적 요인들)

이러한 값들을 루트(근)이라고 한다.

다른 값은 참조 또는 참조 체인에 의해 루트에서 도달 할 수 있는 경우 도달가능한 것으로 간주된다.

예를 들어 로컬변수에 객체가 있고 해당 객체에 다른 객체를 참조하는 속정이 있는 경우 해당 객체는 도달 가능한 것으로 간주된다. 그리고 그것이 참조하는 것들도 도달할 수 있다.

자바스크립트엔진에는 가비지 컬렉터라고하는 백그라운드 프로세스가 있다. 모든 개체를 모니터링하고 연결할 수 없는 개체를 제거한다.

간단한 예

let user = {
  name: "John"
};

이때 user{name: "John"}라는 객체의 참조를 가지고 있다. 하지만 user를 덮어쓰면 어떻게 될까?

user = null;

이제 {name: "John"} 객체에는 도달할 수 없게된다. 접근 가능한 방법이나 참조가 없다. 가비지 콜렉터는 데이터를 폐기하고 메모리를 해제시킨다.

두 참조

유저가 객체를 가진 상태에서 admin에 복사되었다고 해보자.

let user = {
  name: "John"
};

let admin = user;

이전처럼 유저의 참조를 풀어보자.

user = null;

이제는 admin으로 객체에 접근할 수 있기때문에 여전히 객체는 남아있다.

상호 연결된 객체

function marry(man, woman) {
  woman.husband = man;
  man.wife = woman;

  return {
    father: man,
    mother: woman
  };
}

let family = marry(
  {
    name: "John"
  },
  {
    name: "Ann"
  }
);

함수 marry는 서로에 대한 참조를 제공하여 두 객체를 결혼시키고 두 객체를 모두 포함하는 새 객체를 반환한다.

두개의 참조를 제거해보자

delete family.father;
delete family.mother.husband;

여전히 모든 객체에 선이 있지만, John에게 도달하는 선은 없고 나가는건만 있는걸 알 수 있다.

발신참조는 중요하지 않기때문에 John은 도달할 수 없다고 판단되어 메모리에서 제거된다.

고립된 섬

상호 연결된 객체가 어딘가에서 도달할 수 없다면 메모리에서 제거된다.

이전의 소스에서 하나만 바꿔보자.

family = null;

끊어진 객체는 제거된다.

내부 알고리즘

기본 가비지 수집 알고리즘을 마크 앤 스윕이라고 한다. 다음의 단계들이 정기적으로 수행된다.

  • 가비지 컬렉터는 루트를 가져와서 마크(기억)한다.
  • 모든 참조를 방문하고 마크한다.
  • 마크된 객체를 방문하여 해당 참조를 마크한다. 만문한 모든 객체는 추후 동일한 객체를 두번 방문하지 않도록 기억된다.
  • 모든 도달 가능한 참조가 방문될 때까지 계속된다.
  • 마크된것을 제외한 모든 객체가 제거된다.

그외 몇가지 최적화 알고리즘이 있다.

  • 세대 별 수집: 개체는 새로운 것오래된 것의 두 세트로 나뉜다. 많은 객체들이 나타나서, 할 일을 하고, 금장 죽는다. 이러한 것들은 청소되기 쉽다. 오래 살아남은 객체들은 덜 검사 받는다.
  • 증분 수집: 많은 객체가 있고 전체 객체 세트를 한 번에 들러서 마크하려면 시간이 걸리고 실행이 지연될 수 있다. 그로인해 엔진은 가비지 컬렉션을 여러 조각으로 나누려고한다. 그런 다음 조각이 하나씩 실행된다. 변경 사항을 추적하려면 추가 예약이 필요하지만 큰 지연 대신 작은 지연이 여러개 있게 된다.
  • 유휴 시간 수집: 가비지 컬렉터는 CPU가 유휴 상태일때만 실행을 시도하여 실제 작업에 미치는 영향을 줄인다.





© 2017. by isme2n

Powered by aiden