가비지 컬렉션
- 자바스크립트는 도달 가능성이라는 개념을 사용해 메모리 관리를 수행한다.
- 가비지 컬렉터는 모든 객체를 모니터링하고, 도달할 수 없는 객체는 삭제한다. 즉 도달 가능한 상태일 때 메모리에 남는다.
- 가비지 컬렉션은 엔진이 자동으로 수행하므로 개발자는 이를 억지로 실행하거나 막을 수 없다.
- 참조되는 것과 도달 가능한 것은 다르다. 서로 연결된 객체들도 도달 불가능할 수 있다.
삭제 되지 않는 값들
- 태생부터 도달 가능하기 때문에, 명백한 이유 없이는 삭제되지 않는 값들
- 현재 함수의 지역 변수와 매개변수
- 중첩 함수의 체인에 있는 함수에서 사용되는 변수와 매개변수
- 전역 변수
- 기타 등등
이러한 값은 루트(root)라고 부른다.
- 루트가 참조하는 값이나 체이닝으로 루트에서 참조할 수 있는 값
예시
let user = {
name: "John"
}
user = null;
- 위의 코드에서
{ name: "John" }
을 참조하는 것도 모두 사라졌기 때문에 도달할 수 없는 상태가 되었다. 가비지 컬렉터는 John에 저장된 데이터를 삭제하고. John을 메모리에서 삭제한다.
let user = {
name: "John"
};
let admin = user;
user = null;
- 위의 코드같은 경우
user = null
을 해도 admin
이 { name: "John"}
을 여전히 참조하고 있기 때문에 접근을 할 수 있다. 따라서 메모리에서 삭제되지 않는다. ( admin = null
을 하면 삭제됨 )
도달할 수 없는 섬
function marry(man, woman) {
woman.husband = man;
man.wife = woman;
return {
father: man,
mother: woman
}
}
let family = marry({
name: "John"
}, {
name: "Ann"
});
family = null;
- 위의 코드에서
John
과 Ann
은 여전히 서로를 참조하고 있지만 루트의 연결이 사라지면 루트 객체를 참조하는 것이 아무것도 없게 된다. 따라서 John, Ann 두 객체 자체가 도달할 수 없는 상태가 되고, 객체 전부가 메모리에서 제거된다.
내부 알고리즘
가비지 컬렉션의 수행 단계
- 가비지 컬렉터는 루트정보를 수집하고 이를 mark(기억) 한다.
- 루트가 참조하고 있는 모든 객체를 방문하고 이것들을 mark 한다.
- mark 된 모든 객체에 방문하고 그 객체들이 참조하는 객체도 mark 한다. 한번 방문한 객체는 전부 mark 하기 때문에 같은 객체를 다시 방문하는 일은 없다.
- 루트에서 도달 가능한 모든 객체를 방문할 때 까지 3번의 과정을 반복한다.
- mark 되지 않은 객체를 메모리에서 삭제한다.
최적화 기법
- generational collection(세대별 수집) - 객체를 새로운 객체와 오래된 객체로 나눈다. 객체 상당수는 생성 이후 제 역할을 빠르게 수행해 금방 쓸모가 없어지는데 이러한 객체를 '새로운 객체'로 구분한다. 가비지 컬렉터는 이런 객체를 위주로 메모리에서 제거한다. 일정 시간 이상 살아남은 객체는 오래된 객체로 분류하여 가비지 컬렉터가 덜 감시한다.
- incremental collection(점진적 수집) - 모든 객체를 한 번에 방문하고 mark 하는 것은 많은 비용이 들고 성능이 저하된다. 따라서 가비지 컬렉션을 여러 부분으로 분리한 다음 각 부분을 별도로 수행한다. 작업을 분리하고, 변경 사항을 추적하는 데 추가 작업이 필요하지만, 긴 지연을 짧은 지연 여러 개로 분산시킬 수 있다.
- idle-time collection(유휴 시간 수집) - 가비지 컬렉터는 실행에 주는 영향을 최소화하기 위해 CPU가 유휴 상태일 때에만 가비지 컬렉션을 실행한다.
Reference
가비지 컬렉션