본문 바로가기
시작/TIL(Today I Learned)

V8 엔진 메모리 구조 - 힙(Heap)과 스택(Stack)

by 백씨네 2024. 3. 11.
728x90

자바스크립트는 싱글 스레드이기 때문에 V8은 자바스크립트 하나의 컨텍스트당 한 개의 프로세스를 사용한다. 만약 서비스 워커를 사용한다면 워커 또한 각각 새로운 V8 프로세스를 생성한다.

실행 중인 프로그램은 V8 프로세스에서 할당된 일정량의 메모리로 표현되고 이를 Resident Set이라고 한다.

 

V8 프로세스(Resident Set) 하나는 크게 하나의 힙 메모리와 스택 메모리로 나뉜다.

 

 

스택(Stack) 메모리

스택 메모리는 함수 호출과 실행 컨텍스트, 그리고 원시타입의 변수 값을 저장하는 데 사용된다.

  • 실행 컨텍스트와 함수 호출
    • 함수 호출 시 생성되는 실행 컨텍스트를 순서대로 저장하는 구조이다. 실행 컨텍스트는 해당 함수의 변수, 매개변수, 반환 주소 및 기타 실행에 필요한 정보를 포함한다.
    • 함수가 호출될 때마다 새로운 실행 컨텍스가 스택의 맨 위에 push 되고, 함수 실행이 완료되면 pop 되어 제거된다.
    • LIFO(Last In, First Out) 원칙을 따른다.
  • 원시 타입의 데이터 저장
    • 스택 메모리는 원시 타입의 데이터를 저장하는 데 사용된다. 원시 값은 변수에 직접 할당되며, 함수의 실행 컨텍스트 내에 위치한다.
    • 원시 타입의 데이터는 값 자체가 스택에 저장되기 때문에 데이터를 전달할 때는 값의 복사본이 생성되어 전달된다.
  • 효율적인 메모리 관리
    • 스택 메모리는 자동으로 관리되며, 함수 호출과 반환 과정에서 데이터의 할당과 해제가 빠르게 이루어진다.
    • 재귀 함수의 과도한 호출로 인해서 스택 오버플로 가 발생할 수 있다.
      • 스코프와 변수의 접근성
      • 스택에 저장된 변수는 해당 변수가 선언된 함수의 스코프 내에서만 접근할 수 있다.
      • 함수가 종료되면 해당 함수의 실행 컨텍스트와 함께 스택에서 제거되므로, 해당 함수의 로컬변수에는 더 이상 접근할 수 없다.

 

 

힙(Heap) 메모리

힙은 동적으로 할당된 객체들이 저장되는 메모리 영역이다. JS에서 객체, 문자열, 클로저 등은 힙에 저장된다. 힙은 구조화되지 않은, 즉 고정되지 않는 메모리 할당에 사용되며, 가비지 컬렉터(GC)에 의해 관리된다.

  • New Space (Young Generation)
    • New space는 빈번하게 발생하는 소규모의 가비지 컬렉션을 위해 설계된 영역이다.
    • 새로 만들어지는 모든 객체를 저장하고 이 객체들은 짧은 생명주기를 가진다.
    • 주로 Scavenge GC(마이너 GC) 알고리즘을 사용한다.
    • Semi-space라 불리는 두 개의 부분으로 나뉜다. (From-sapce와 To-space)
    • New Space 영역의 크기는 --min_semi_space_size--max_semi_space_size V8엔진의 플래그 값을 사용해 조정할 수 있다.
    • 일부 객체가 여러 번의 가비지 컬렉션을 살아남는 경우, 더 긴 생명주기를 가질 가능성이 높다고 판단되어 Old Space로 이동된다. (promotion)
  • Old Space (Old Generation)
    • New Space에서 살아남은 객체들이 이동하는 영역이다.
    • Mark-Sweep 및 Mark-Compact GC(메이저 GC) 알고리즘을 사용한다. (Incremental Marking 알고리즘도 있다.)
    • Old Space 영역의 크기는 --initial_old_space_size--max_old_space_size V8 엔진의 플래그 값을 사용해 조정할 수 있다.
    • Old pointer space, Old data space로 나뉜다.
      • old pointer space : 살아남은 객체들을 가지며, 이 객체는 다른 객체를 가리키는 포인터를 포함하고 있어, 객체 간의 관계를 나타낸다.
      • 스칼라 값(원시 데이터)이나 포인터가 아닌 데이터를 저장한다. number, string, boolean 값 등이 포함될 수 있다.
  • Large Object Space
    • 일반적인 가비지 컬렉션 과정에서 처리하기에 너무 큰 객체들은 별도로 관리하기 위한 공간이다. 대형 객체들은 이 공간에 직접 할당되며, 가능한 복사를 피하여 관리된다.
  • Code Space
    • JIT 컴파일러에 의해 컴파일된 실행 가능한 코드를 저장한다. 이 공간은 코드를 효율적 실행을 위해 최적화되어 있다.
  • Cell Space, Property Cell Space, Map Space
    • 각 영역은 모두 같은 크기의 객체들을 포함하며, 특수한 목적을 가진 메모리 공간들이다. 그래서 저장되는 객체의 종류에 제약을 두어 가비지 컬렉션보다 단순하고 효율적으로 만든다.
    • Cell Space : Cells를 저장하는 공간으로 Cell은 작은 데이터 조작이나, 단일 포인터를 저장하는 데 사용한다. 간단한 데이터 구조나 참조를 위한 공간으로 활용할 수 있다.
    • Property Cell Space : Property Cells를 저장하는 공간이다. 객체의 속성에 대한 메타 데이터나 속성의 값 자체를 저장하는 데 사용한다. 객체의 속성정보를 중앙화하여 관리함으로써, 속성 접근 시의 성능 최적화에 기여한다.
    • Map Space : Map은 V8 엔진에서 객체의 구조를 설명하는 데 사용되는 중요한 메타데이터이다. 객체의 타입, 속성의 구조, 프로토타입 체인 정보 등을 담고 있다. 이를 통해 객체의 속성 접근과 타입 최적화가 이루어진다. 객체 지향 프로그래밍에서의 클래스와 유사한 역할을 함

출처 : ToastUI 블로그 -https://ui.toast.com/weekly-pick/ko_20200228

반응형

댓글