- 메모리
- 할당 > 사용 > 해제 순
- js엔진은 garbage collector로 사용하지 않는, 즉 참조되지 않는 메모리를 알아서 해제해줌
- 변수를 선언할 때 js에서 일어나는 일 ⇒ 변수에 고유 식별자를 생성하고 메모리에 있는 주소를 할당
- 한 변수(이하 변수2)의 값으로 기존의 다른 변수(이하 변수1)를 할당? ⇒ 둘 다 변수1의 주소를 가리킴
- 변수1의 값을 변경한다면? ⇒ 변수1은 새로운 주소를 가리키고(즉, 메모리가 새로 할당), 변수2는 이전의 변수1 주소 였던 곳을 여전히 가리킴
- js에서 원시타입은 변경이 불가능하기 때문에 새로운 주소를 가리키는 것임
Garbage Collector
- 가비지 컬렉션은 엔진이 자동으로 수행하므로, 이를 억지로 실행하거나 막을 수 없다.
- GC 기준은 도달가능성(Reachability)
- 루트(Root) : 태생부터 도달이 가능하여 명백한 이유없이는 삭제되지 않는 값
- 현재 함수의 지역변수와 매개변수
- 중첩 함수의 체인에 잇는 함수에서 사용 되는 변수와 매개변수
- 전역 변수 등
- 루트가 참조하는 값이나 체이닝으로 루트에서 참조할 수 있는 값은 도달 가능한 값이다.
- ex)
let user = { name: "John" };
로 선언하고user
를 다른 값으로 재할당 하면, 기존의{ name: "John" }
객체는 참조가 사라지고, 여기에 도달할 방법이 없다. 이 때 GC가 해당 객체를 메모리에서 삭제한다.
- 루트를 출발지로해서 참조가 되어 도달 가능한 객체여야 한다.
- 도달할 수 없는 섬(Unreachable Island) : 루트가 접근할 수 없고 자기들끼리 참조하는 객체 덩어리, GC는 이 섬을 구성하는 객체 전부를 메모리에서 삭제한다.
- GC가 자동하는 내부 알고리즘 ⇒ "mark-and-sweep" 알고리즘
1) 루트(Root)에 접근하여 Mark(기억)한다.
2) 루트 참조하는 객체에 접근하여 Mark한다.
3) 객체가 참조하는 객체에 접근하여 Mark한다. (루트에서 도달 가능한 모든 객체를 방문할 때까지 반복.)
4) 더이상 접근할 객체가 없으면, Mark되지 않은 모든 객체를 메모리에서 삭제(Sweep)
- GC 최적화 기법들 중 세가지
- generational collection(세대별 수집) : 오래된 객체와 새로운 객체를 구분하여, 새로운 객체는 엄격하게 감시하여 제거하고 오래된 객체는 덜 감시함.
- 객체의 상당수는 생성 이후 제 역할을 빠르게 수행해 금방 쓸모가 없어지기 때문
- 오래된 객체(일정 시간 이상 동안 살아남은 객체)는 덜 감시함.
- incremental collection(점진적 수집) : 방문해야할 객체가 많으면 부하가 높아진다. 모든 객체를 한번 다 방문하지말고, 여러부분으로 나누어 각 부분을 별도로 GC를 진행한다.
- 차이로 인한 변경사항을 추적하는데 추가작업이 필요하지만, 짧은 지연 여러 개로 분산시킬 수 있다.
- idle-time collection(유휴 시간 수집) : CPU 부하를 덜 주기위하여, idle 상태에서만 GC를 실행함.