[TIL] 프로세스 메모리

krkorklo·2022년 8월 18일
0

TIL

목록 보기
4/29
post-thumbnail

프로세스 메모리

프로세스는 실행되고 있는 프로그램으로 프로세스는 각 메모리 공간을 시스템으로부터 할당받는다

  • Text(code)
    • 코드와 상수가 정의
    • CPU가 해당 영역에서 명령어를 하나씩 가져와 처리
    • 읽기만 가능해 데이터를 저장하려고하면 충돌이 발생해 프로세스가 중지
  • Data
    • 전역 변수와 정적 변수가 저장되어있는 영역
    • 초기화된 전역 변수가 존재 (비휘발성 메모리 ROM에 저장)
    • BSS(Block Stated Symbol) : 초기화되지 않은 전역 변수가 저장
  • Heap
    • 필요에 따라 동적으로 할당되는 동적 메모리 영역
    • 메모리 주소값에 의해서만 참조되는 영역
    • 런타임(프로그램 동작 시)에 크기가 결정
  • Stack
    • 함수 인자값, 함수 내 지역 변수, 함수 반환 주소 등(잠시 사용되었다가 사라지는 데이터)이 저장되는 영역
    • 함수 호출의 전반적인 처리와 리턴을 담당
    • 컴파일 타임(로드 시)에 크기가 결정

스택 프레임

  • 함수가 호출되었을 때 함수가 가지는 공간 구조
  • 함수가 동작을 종료하고 복귀 주소로 돌아갈 때 스택 프레임은 소멸
  • SP(Stack Pointer) : 현재 위치를 가리키는 레지스터
  • BP(Base Pointer = Frame Pointer) : 함수의 시작 시점으로 스택 프레임이 소멸하기 전까지 고정값으로 해당 값을 기준으로 삼아 상대적 주소, Offset을 사용할 수 있다

프로세스 메모리 관리 - Node.js

V8 Engine

  • JavaScript는 인터프리터 언어(코드를 한줄씩 읽어가며 명령을 바로 처리 - 번역과 실행이 동시에 발생)로 코드를 해석하고 실행하는 실행기가 필요 → V8 Engine
  • JS를 Assembly code로 컴파일
  • Node.js는 V8 Engine을 떼어와서 JS를 실행할 수 있는 자바스크립트 런타임

JIT Compiler

  • JIT Compiler(Just-In-Time)는 동적 컴파일(인터프리터)과 정적 컴파일(Compiler)을 합친 것으로 실행시점에서 인터프리터 방식으로 바이트 코드를 생성
  • 바이트 코드를 기계어 코드로 만들고 캐싱해 같은 함수가 여러번 불릴 때 매번 기계어 코드가 생성되는 것을 방지 (인터프리터의 비효율성 보완)

  • V8 Engine은 JavaScript 컨텍스트 당 하나의 프로세스를 사용
    Resident Set
  • 메모리를 크게 Stack, Heap 영역으로 구분
    • Heap
      • New 영역과 Old 영역으로 나뉘어 Garbage Collection으로 관리
      • New Space : 짧은 생명주기를 가져 Minor Garbage Collection에 의해 관리
      • Old Space : 두 번의 Minor Garbage Collection 주기동안 New Space에서 살아남은 객체들로 Major Garbage Collection에 의해 관리
      • Large Object Space : 매우 큰 객체들이 존재해 Garbage Collection에 걸리지 않음
      • Code space : JIT 컴파일러가 컴파일된 코드 블록을 저장 - 실행 가능한 메모리가 존재
    • Stack
      • Frame 단위로 묶여서 올라간다
      • 함수가 호출되면 해당 함수 이름으로 된 Frame 영역이 생기며 함수가 끝나기 전까지 해당 Frame 영역에 변수들이 적재
  • Minor Garbage Collection (Scavenger)
    • New Space 영역을 정리하는 역할
    • 새 객체를 위한 공간을 예약하기 위해 할당 포인터가 증가할때 포인터가 공간의 끝에 도달하면 GC가 트리거
    • 자주 발생하며 빠르게 진행
  • Major Garbage Collection
    • Old Space 영역을 정리하는 역할
    • Old Space 공간이 부족하다고 판단할 때 트리거

가상 메모리

메모리를 관리하는 방법 중 하나로 각 프로그램에 실제 메모리 주소가 아니라 가상의 메모리 주소를 주는 방식
→ 실제 물리 메모리가 가지고 있는 크기를 논리적으로 확장해서 사용 가능

  • 물리 메모리가 가진 공간 이상으로 데이터를 저장할 수는 없지만 주기억장치나 레지스터 등의 공간을 연속적으로 가상 공간에 매핑
  • 가상 메모리는 페이지 단위, 물리 메모리는 프레임 단위로 관리

페이징

  • Virtual Memory의 Page가 하나의 Frame을 할당받으면 물리 메모리에 위치
  • Frame을 할당받지 못한 페이지는 외부 저장장치에 저장

Page Table

  • 프로세스의 페이지 정보를 저장하고 있는 테이블
  • Page에 매핑되는 Frame을 찾을 때 참조
  • key : 페이지 번호
  • value : Page와 매핑된 Frame번호
  1. 페이지 번호(P)를 사용해 페이지 테이블에 접근
  2. Page Table에서 해당 번호에 해당하는 Frame 시작 주소를 얻음
  3. 프레임 시작 주소(F)와 변위(d)를 통해 물리 주소에 접근

  • 가상 주소를 물리 주소로 변환하는 과정은 MMU라는 하드웨어가 실행
  • TLB(Translation Look aside Buffer) - 페이지 정보 캐시에서 가상 주소를 검색 후 엔트리가 존재하면 바로 물리 메모리로 주소 변환 후 데이터를 가져오고, 엔트리가 없다면 페이지 테이블을 참조해서 변환

  • 페이지가 실제 물리 메모리에 없을 때 Page Fault Interrupt 발생
  • Page Fault가 발생하면 운영체제가 해당 페이지를 물리 메모리에 올림

페이지 테이블 종류
1. Multi-level Page Table : 페이지 테이블을 여러 단계로 쪼개어 사용
2. Hashed Page Table : 해시 데이블에 존재하는 엔트리를 참조해서 물리 주소를 찾음
3. Inverted Page Table : 프로세스 별 페이지 테이블이 아닌 시스템 하나만의 페이지 테이블을 두는 방식

페이지 교체 정책

1. FIFO

  • 가장 먼저 메모리에 올라온 페이지를 가장 먼저 내보냄
  • 구현이 간단하지만 성능이 좋지 않음

2. OPT(Optimal) 알고리즘

  • 앞으로 가장 오랫동안 사용하지 않을 페이지를 교체
  • Page Fault 발생이 가장 적지만 실제로 구현 불가한 정책

3. LRU 알고리즘

  • 가장 오랫동안 사용하지 않은 페이지를 교체
  • 성능이 좋은 편으로 많은 운영체제가 채택

4. LFU 알고리즘

  • 가장 참조횟수가 적은 페이지를 교체
  • 교체 대상이 여러 개면 가장 오랫동안 사용하지 않은 페이지를 교체

5. MFU 알고리즘

  • LFU와 반대로 참조 횟수가 가장 많은 페이지를 교체

6. NUR(Not Used Recently) 알고리즘 - Clock

  • 최근에 사용하지 않은 페이지를 교체하지만 교체되는 페이지의 참조 시점이 가장 오래되었다는 것은 보장하지 못함
  • 동일 그룹 내에서 무작위의 선택
  • Reference Bit : 페이지가 참조되지 않았을 때 0, 참조되었을 때 1
  • Modified Bit : 페이지의 내용이 변경되지 않았을 때 0, 변경되었을 때 1

Fragmentation

  • 메모리 공간이 작은 조각으로 나뉘어 사용 가능한 메모리가 충분하게 존재하지만 할당이 불가능한 상태
  • External Fragmentation : 메모리가 할당되고 해제되며 작은 메모리가 중간중간 존재 → 사용하지 않는 메모리가 많이 존재해 총 메모리 공간은 충분하지만 실제로 할당할 수 없는 상황
  • Internal Fragmentation : 메모리를 할당할 때 프로세스가 필요한 양보다 더 큰 메모리가 할당되어서 프로세스에서 사용하는 메모리 공간이 낭비되는 상황

Fragmentation 해결 방법

  • Paging 기법
    • 가상 메모리를 사용해 External Fragmentation을 해결하는 방법
    • 가상 메모리를 같은 크기의 블록으로 나눈 것을 페이지라 하고 RAM을 페이지와 같은 크기로 나눈 것을 프레임이라 할 때, 사용하지 않는 프레임을 페이지에 옮기고, 필요한 메모리를 페이지 단위로 프레임에 옮기는 기법
    • 페이지와 프레임을 대응시키기 위해 page table 필요
    • 연속적이지 않은 공간도 활용할 수 있어 External Fragmetation 문제 해결 가능
    • 필요한 메모리가 page의 배수가 아닌 경우 Internal Fragmentation 발생
    • 페이지 크기를 작게하면 Internal Fragmentation 문제를 해결할 수 있지만 paging mapping 과정이 많아져 비효율적일 수 있음
  • Segmentation 기법
    • 가상 메모리를 사용해 Internal Fragmentation을 해결하는 방법
    • 가상 메모리를 서로 크기가 다른 논리적 단위 세그먼트로 분할해서 메모리를 할당하는 방식
    • 세그먼트들의 크기가 달라 미리 분할할 수 없고 메모리에 적재될 때 빈 공간을 찾아 할당
    • mapping을 위한 세그먼트 테이블이 필요
    • 필요한 만큼 할당받아 Internal Fragmentation을 일어나지 않지만 중간에 프로세스가 메모리를 해제하면 생기는 External Fragmentation은 존재
  • Memory Pool
    • 필요한 메모리 공간을 필요한 크기, 개수만큼 사용자가 직접 지정해서 미리 할당받아놓고 필요할 때마다 사용하고 반납하는 기법
    • 할당과 해제가 반복되며 Fragmentation을 발생시킬 수 있으나 미리 공간을 할당하고 쓴 후 반납하기 때문에 External Fragmentation가 발생하지 않고 필요한 크기만큼 할당받아 Internal Fragmentation도 발생하지 않음
    • 메모리의 할당, 해제가 잦은 경우 효과적
    • 할당하고 사용하지 않는 순간에도 할당되어 있으므로 메모리 누수가 존재

참고자료
https://medium.com/@jungkim/스위프트-타입별-메모리-분석-실험-4d89e1436fee
https://deepu.tech/memory-management-in-v8/
https://hwan-shell.tistory.com/343
https://wogh8732.tistory.com/395
https://gamedevlog.tistory.com/85
https://jeong-pro.tistory.com/91

0개의 댓글