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

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

  • 불필요한 노드(페이지에 없는 노드 또는 해제되어야 할 노드)를 찾을 수 있다.

    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의 크기가 증가 하고 있다.

test1.png test2.png

참고


© 2023, Customized by Joon