Jun 개발노트

How to Find Memory leak

March 06, 2022

작성이유

  • 메모리 Leak 발견했고 해결했다!
  • 메모리 Leak과 찾는방법(개발자도구)에 대해서 정리하고 싶어

트러블 슈팅

전체 로직 없으니… 아주 작은 문제같다.. ㅜㅜ

// websocket으로 받는 데이터: newTransactions
const data = [...newTransactions, data (1일치 데이터)]
  • 화면에 표시될 데이터 : 24시간전부터 지금까지 데이터
  • 문제

    • 시간이 지날수록 outdated 데이터가 늘어났다.
    • 개발환경에서는 노출되지 않았지만, 배포 후 급격히 늘어나는 Heap…(개발자 도구)
  • 해결방법

    • outdated 데이터 삭제

Memory Life Cycle

  • 할당 : Allocate the memory you need, malloc()
  • 사용 : Use the allocated memory (read, write)
  • 해제 : Release the allocated memory when it is not needed anymore , free()

JS Variable Memory

  • 함수 실행컨텍스트내에 VO(ariable object)에 해당 변수가 선언
  • reference의 경우, Heap에 할당이 되어 포인터로 해당 변수를 가르키게 된다.

    • main context에 할당된 변수를 전역 변수라고 한다.

jsMemory.png

JS GC Algorithm(Mark And Sweep)

  • 참조되고 있는 메모리(Marking)를 제외하고 제거(사용되지 않는 메모리)

markAndSweep1.png markAndSweep2.png markAndSweep3.png markAndSweep4.png

Memory Leak

더 이상 사용하지 않는 메모리를 정리하지 못할때 ㅠㅠ..

1. 전역변수

function foo(arg) {
    bar = "this is an explicit global variable";
}

2. 타이머와 콜백

const someResource = getData();
setInterval(function() {
    const node = document.getElementById('Node');
    if(node) {
        // Do stuff with node and someResource.
        node.innerHTML = JSON.stringify(someResource));
    }
}, 1000);

3. DOM 외부의 참조

const detachedTree;

function create() {
  const ul = document.createElement('ul');
  for (var i = 0; i < 10; i++) {
    var li = document.createElement('li');
    ul.appendChild(li);
  }
  detachedTree = ul;
}

document.getElementById('create').addEventListener('click', create);

4. 클로져

var theThing = null;
var replaceThing = function () {
  var originalThing = theThing;
  var unused = function () {
    if (originalThing)
      console.log("hi");
  };
  theThing = {
    longStr: new Array(1000000).join('*'),
    someMethod: function () {
      console.log(someMessage);
    }
  };
};
setInterval(replaceThing, 1000);

Memory 관련 개발자도구

1. Heap snapshot

  • 현재 Heap영역의 메모리 할당 내역을 보여준다.

heaptab.png

2. Allocation instrumentation on timeline

var x = [];

function grow() {
    x.push(new Array(1000000).join('x'));
}

document.getElementById('grow').addEventListener('click', grow);

timeline.png

3. Console Performance Monitor

consolemonitor.png

이 자료를 가지고 내가 지금 할 수 있는거?

  • 불필요한 노드(페이지에 없는 노드 또는 JS가 참조되 있는 노드)를 찾을 수 있다.

    var detachedTree;
    
    function create() {
      var ul = document.createElement('ul');
      for (var i = 0; i < 10; i++) {
        var li = document.createElement('li');
        ul.appendChild(li);
      }
      detachedTree = ul;
    }
    
    document.getElementById('create').addEventListener('click', create);
    • 클릭 이벤트가 발생할때마다, Node와 Heap의 크기가 증가 하고 있다.

![test3.png](../../assets/memory/test3.png

![스크린샷 2022-03-06 20.51.34.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6cd7113a-339c-44fa-abcb-cee75d2ac87f/스크린샷_2022-03-06_20.51.34.png)

![스크린샷 2022-03-06 20.51.47.png](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6fe77b18-a831-4d8e-983a-b1652ce2e23d/스크린샷_2022-03-06_20.51.47.png)

참고


Written by Junho You 배운것을 기록하자