Develop Note by J.S.

[Programming] Memory Leak (메모리누수 with V8) 본문

Knowledge/Programming

[Programming] Memory Leak (메모리누수 with V8)

js-web 2023. 8. 21. 10:46
반응형

1. Memory Leak 

 - 개발자가 의도하지 않은 메모리가 더 이상 사용되지 않음에도 해제되지 않고 지속적으로 메모리를 점유하고 있는 현상을 말하며, 이로 인한 버그발생 및 서비스장애를 발생시킵니다. 

 

 - 대표적인 메모리 관련 이슈는 3가지 유형으로 나타납니다.

  1) 페이지가 시간이 지남에 따라 느려지는 현상
       - 주요원인 : Memory Leak

  2) 페이지가 처음부터 일관적으로 느리거나, 급작스럽게 느려지는 현상

       - 주요원인 : Memory Bloat(메모리 팽창)으로 볼수 있으며 메모리 소비의 급작스런 증가로 발생

  3) 페이지가 끊키는 현상

       - 주요원인 : GC가 너무 자주 발생되는 경우

2. Memory Lifecycle

메모리 생명주기 : 할당 -> 사용 -> 해제

3. 메모리 구조(V8 Engine)

Stack
 - LIFO(후입선출) 방식으로 메모리를 할당하며 변수식별자, 원시타입 데이터, this관리 및 코드 실행 순서 관리 등의 역할을 수행합니다.
 - 컴파일 타임에 크기가 결정됩니다.
Heap 
 - 자바스크립트의 동적 메모리 할당을 위해 미리 예약해둔 메모리 공간이며, Array, Function, Object 와 같은 참조 유형을 할당하기 위한 공간입니다.
 - 런타임에 크기가 결정됩니다.


 - V8엔진에서는 Resident Set이라는 빈 공간이 할당 됩니다. 자바스크립트는 싱글 스레드이기 때문에 스택 메모리는 1개만을 가집니다. 스택은 함수 호출 종료 시 OS에 의해 정리되지만 힙의 경우 GC에 의해 정리되고 있습니다.

 - 힙 영역은 코드, Map, 속성 등 여러 Space로 이루어져 있으며 GC가 발생되는 부분은 New SpaceOld Space입니다.

 - New Space : 새로 생성된 Object들이 저장되는 장소

 - Old Space :  New space에서 마이너 가비지 컬렉션이 2번 발생할 동안 살아남은 객체들이 저장되는 장소 

4. GC (가비지 컬렉션) 

Weak Generational Hypothesis(약한 세대 가설)은 대부분의 경우 신규 객체가 오래된(오래 살아남은)객체보다 쓸모없어질 가능성이 높다는 가설로, 매번 GC가 모든 객체를 검사하기에 비효율적 이므로 Space나누어 생명주기가 짧은 Object는 New Space에서 마이너 GC가 컬렉션을 수행하고, 메모리 사이즈가 큰 Old Space는 메이저 GC가 컬렉션을 수행합니다.

 

 - Minor GC : 두 개의 Semi Space 중 한 곳에서만 신규 Object가 생성되고, 메모리가 꽉 찼을 때 GC 수행 후 살아남은 Object를 다른 Semi Space로 옮긴 뒤 역할을 바뀌게 됩니다. 이후 신규 Object 생성부터 GC 수행 후 저장 공간의 역할을 동일하게 반복합니다.  (Default Semi Space Max Size : 64bit cpu - 16Mbyte / 32bit cpu - 8Mbyte )

 - Major GC : Minor GC 2회 수행 이후 살아남은 Object를 Old Space로 이동하며, 해당 Old Space공간이 충분하지 않다고 판단될 때 Major GC가 실행됩니다. (Default Old Space Max Size : 64bit cpu - 512Mbyte / 32bit cpu - 1024Mbyte )

 

* 가비지 컬렉션 방식

1) Reference Counting

 - 어떠한 곳에서도 참조되지 않은 객체는 사용되지 않는 것으로 간주하고 메모리를 해제합니다. 하지만 순환 참조 방식으로 구현 코드는 해제가 불가능합니다.

function task(n, d) {
    // ...

    reporter = { ... };
    assignee = { ... };

    reporter.assignee = assignee;
    assignee.reporter = reporter;
};

Circular Dependencies(순환 종속성) : 각 Object가 서로를 참조하는 경우로, 사용하지 않는 경우 Reference Counting 방식의 GC에는 해결되지 않음. 
 - 현재 Reference Counting 방식은 최신브라우저에서는 사용되지 않습니다. 

 

2) Mark-and-sweep

 - Mark-and-sweep 알고리즘은 가비지 컬렉션을 위해 많은 프로그래밍 언어에서 사용되는 알고리즘

 - Root(Global Object)로 부터 시작하여 계층구조를 반복하여 내려가면서 (DFS - 깊이우선탐색) 각 요소들을 탐색(Mark)한 뒤, 도달할 수 없는 객체를 찾아 해제(Sweep)합니다.

 

* Stop The World

가비지 컬렉션이 수행될 때 프로그램이 잠시 멈추게 되는 현상을 stop-the-world라고 하며 이 시간이 길어 질수록 렌더링 지연으로 인한 UX경험이 나빠지게 됩니다. 이런 증상을 해결하기 위하여 V8 - GC 프로젝트(Oricono)에서 병렬, 증분, 동시성 방법을 활용하여 성능이 개선되고 있습니다. 

 

 

참고사이트

https://blog.logrocket.com/escape-memory-leaks-javascript/

https://developer.mozilla.org/ko/docs/Web/JavaScript/Memory_management#%EC%B0%B8%EC%A1%B0-%EC%84%B8%EA%B8%B0reference-counting_%EA%B0%80%EB%B9%84%EC%A7%80_%EC%BD%9C%EB%A0%89%EC%85%98

https://fe-developers.kakaoent.com/2022/220519-garbage-collection/

https://v8.dev/blog/trash-talk

반응형