메모리 구조는 크게 동적 영역
과 정적 영역
으로 나뉜다.
동적 영역
: Stack, Heap정적 영역
: TEXT(Code), GVAR/BSS힙과 스택은 같은 메모리 영역
을 공유한다.
힙은 낮은 메모리 주소
부터 할당받고 (예: 0x00000000 ...)
스택은 높은 메모리 주소
부터 할당받는다. (예: 0xffffffff ...)
함수 호출
및 지역 변수 관리
를 위해 사용된다.
함수가 호출될 때마다 새로운 스택 프레임이 생성되고, 함수가 반환될 때 해당 프레임이 제거된다.
스택 영역은 프로세스의 동적 메모리 할당
과 관련되어 있으며, 함수 호출 및 지역 변수 사용에 필요한 메모리를 관리한다.
스택 프레임
스택에는 함수의 매개변수, 호출이 끝난 뒤 돌아갈 반환 주소값, 함수에서 선언된 지역 변수 등이 저장된다.
이렇게 스택 영역에 차례대로 저장되는 함수의 호출 정보를 스택 프레임(stack frame)이라고 한다.
이러한 스택 프레임 덕분에 함수의 호출이 모두 끝난 뒤에, 해당 함수가 호출되기 이전 상태로 되돌아갈 수 있습다.
함수가 호출되면 스택에는 함수의 매개변수, 호출이 끝난 뒤 돌아갈 반환 주소값, 함수에서 선언된 지역 변수 등이 저장됩니다.
이렇게 스택 영역에 차례대로 저장되는 함수의 호출 정보를 스택 프레임(stack frame)이라고 합니다.
이러한 스택 프레임 덕분에 함수의 호출이 모두 끝난 뒤에, 해당 함수가 호출되기 이전 상태로 되돌아갈 수 있습니다.
동적으로 할당
되는 메모리 영역이다.
프로그래밍 언어의 메모리 할당 함수(예: malloc, new 등)를 통해 동적으로 할당된다.
힙 영역의 메모리는 프로그램 실행 중에 동적으로 할당되고 해제될 수 있다.
힙 영역은 프로세스의 동적 메모리 관리
와 관련되어 있다.
프로그램의 실행 코드가 저장되는 영역
이다.
프로그램이 실행되면 텍스트 영역의 코드가 CPU에 의해 실행된다.
텍스트 영역은 프로그램의 실행 코드를 저장하며, 일반적으로 읽기 전용으로 설정됩니다.
여기에 저장된 우리의 코드는 컴파일러로 번역된 기계어
형태로 저장되어 있다.
프로그램 전체에서 사용되는 전역 변수
가 저장되는 영역이다.
프로그램이 시작될 때 전역 변수가 초기화되며, 프로그램 전체에서 접근할 수 있다.
글로벌 변수 영역은 프로세스의 정적 메모리 관리
와 관련되어 있습다.
BSS 영역
초기화되지 않은 전역변수들을 저장한다.
자바스크립트를 해석하는 인터프리터로, 구글에서 개발한 엔진이다.
V8 엔진은 C++로 작성되었으며, 이로 인해 C++ 애플리케이션에 V8 엔진을 내장할 수 있다.
자바스크립트는 싱글 스레드
언어이므로, V8은 일반적으로 하나의 프로세스를 사용한다.
단, 서비스 워커(Service Worker)를 사용하는 경우에는 워커의 개수만큼 추가적인 프로세스를 생성한다.
실행 중인 JavaScript 프로그램은 V8 프로세스에 할당된 일정량의 메모리로 표현되며, V8 프로세스가 실제로 사용하고 있는 물리적 메모리 크기를 Resident Set Size(RSS)
라 한다.
Resident Set Size(RSS)은 프로세스가 실제로 물리적 RAM에 사용하고 있는 메모리 크기를 나타낸다. 이는 프로세스가 현재 사용하고 있는 실제 메모리 크기를 의미한다.
RSS도 다른 프로세스 모델과 마찬가지로 운영체제마다 메모리 관리 방식이 다르기 때문에 운영체제에 따라 값(메모리에 할당된 값)이 달라질 수 있다.
힙은 V8 엔진의 동적 메모리 할당 영역
을 의미한다.
힙에는 동적으로 생성된 객체, 배열 등의 데이터가 저장되며 메모리 관리를 위해 가비지 컬렉션
이 사용된다.
또한, 힙은 스택 메모리보다 크기가 크다.
New space(Young generation)
Old space(Old generation)
Large object space
Code space
Call space
Propert cell space
Map space
스택은 V8 엔진마다 하나만 가질 수 있으며 메서드와 함수 프레임, 원시 값, 객체 포인터 등 정적 데이터가 저장되는 메모리 영역이다.
스택 메모리는 LIFO(Last-In-First-Out)
구조를 가지며, 함수 호출과 반환 시 동적으로 할당/해제
된다.
V8의 Stack 영역 관리는 운영체제에 위임하여 관리한다.
스택 메모리의 크기는 일반적으로 작은 편이며, 스택 오버플로우 등의 문제가 발생할 수 있다.
V8의 가비지 컬렉션이 일어나는 부분은 New space와 Old space부분으로 동작방식은 다음과 같다.
세대 구분 (Generational Hypothesis)
V8은 객체를 신생 세대(Young Generation)
와 노령 세대(Old Generation)
로 구분한다.
대부분의 객체는 생성 후 빠르게 소멸되므로, 신생 세대에서 효과적으로 관리한다.
오래 살아남은 객체는 노령 세대로 이동시켜 관리한다.
Scavenge 알고리즘 (Young Generation GC)
신생 세대에서는 Scavenge 알고리즘
을 사용한다.
신생 세대는 두 개의 반 공간(semi-space/ From공간, To 공간)으로 나뉜다.
1) 새로운 객체는 From 공간에 할당되고, GC 발생 시 살아남은 객체는 To 공간으로 복사된다.
2) 공간을 교체하며 GC를 수행하므로 효율적이다.
Mark-Sweep-Compact 알고리즘 (Old Generation GC)
노령 세대에서는 Mark-Sweep-Compact 알고리즘을 사용한다.
1) 먼저 살아있는 객체를 표시(Mark)한다.
2) 표시되지 않은 객체를 제거(Sweep)한다.
3) 마지막으로 메모리를 압축(Compact)하여 단편화를 해결한다.
증분 GC (Incremental GC)
GC 작업을 단계적으로 나누어 수행하여 중단 시간을 줄인다.
사용자 코드 실행과 GC 작업을 번갈아 수행한다.
참고
CS05 - 메모리구조, CPU, 가상 메모리
프로세스 메모리(스택, 힙, 데이터 영역, 코드 영역) 구조 개념 및 특징
TCP - 스택 프레임
스택 프레임(Stack Frame)이란?
[TIL] 프로세스 관리
V8 엔진 내부의 메모리 관리
자바스크립트 v8 엔진의 가비지 컬렉션 동작 방식