• 자바스크립트 메모리 누수 :: 마이구미
    Javascript 2016. 7. 13. 14:39
    반응형

    이전 글 이후 다시 조금 더 다뤄볼 예정으로 글을 작성하게 되었다.

    이전 글을 보고 오길 바란다.

    IBM에서 작성된 글을 통해 진행할 것이다.

    예제를 통해 진행할 것이므로 실습해보자.


    크롬 개발자 도구에서 탭 중 Profiles 탭을 이용할 것이다.

    Profiles의 기능은 아래와 같다.


    웹페이지의 javascript, css 등의 성능을 측정하여 어디에서 병목이 발생하는지 확인,

    메모리 상태 스냅샷을 찍어서 메모리 누수가 일어나는 부분 확인


    profiles



    일단 셋팅하자.

    index.html

    <html> <head> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script> </head> <body> <button id="start_button">Start</button> <button id="destroy_button">Destroy</button> <script src="assert/scripts/leaker.js" type="text/javascript" charset="utf-8"></script> <script src="assert/scripts/main.js" type="text/javascript" charset="utf-8"></script> </body> </html>

    main.js

    $("#start_button").click(function(){ if(!leak){ return; } leak = new Leaker(); leak.init(); }); $("#destroy_button").click(function(){ leak = null; }); var leak = new Leaker();

    leaker.js

    var Leaker = function(){}; Leaker.prototype = { init:function(){ }, };


    웹 페이지에 접속하면 코드상으로 보면 변수 leak에 Leaker 객체를 생성했다는 것을 알 수 있다.

    이것을 스냅샷을 통하여 확인해보자.


    snapshot


    첫번째 스냅샷에서 Summary를 통해 Leaker를 검색하면 위와 같은 결과를 얻을 수 있다.

    그렇다면 이제 Destory 버튼을 클릭해보자.

    클릭을 하면 leak가 null이 되면서 아무도 참조하고 있지 않아 GC가 수행되겠지?

    스냅샷을 다시 한번 실행하여 확인해보자. (까만 똥끄라미 점 누르면 된다)


    스냅샷


    그 결과 Summary에서는 아무것도 검색되지 않을 것이다.

    Comparison로 바꿔 보면 Delta가 -1이 되어있다.

    Leaker 객체를 참조하고 있는 것이 아무것도 없어 GC가 수행된 것이다.


    이번에는 다음과 같이 소스를 바꿔보자.

    leaker.js

    var Leaker = function(){}; Leaker.prototype = { init:function(){ this._interval = null; this.start(); }, start: function(){ var self = this; this._interval = setInterval(function(){ self.onInterval(); }, 100); }, destroy: function(){ if(this._interval !== null){ clearInterval(this._interval); } }, onInterval: function(){ console.log("Interval"); } };

    main.js

    $("#start_button").click(function(){ if(!leak){ return; } leak = new Leaker(); leak.init(); }); $("#destroy_button").click(function(){ //leak.destroy(); leak = null; }); var leak = new Leaker();


    위의 소스를 해석해보자면,

    start 버튼을 클릭 시 setInterval 메소드를 통해 0.1초마다 계속 호출을 하고 있다.

    이 경우 destory 버튼을 클릭하여 leak를 null시킨다.

    이것 또한 Leaker 객체를 참조하는 것은 없기 때문에 GC가 수행되어야한다.

    하지만 참고한 글에서는 이벤트 리스너가 계속 존재하기 때문에 GC가 수행되지 않는다고 한다.

    (참고한 IBM에서 작성된 글은 2012년 11월경에 쓰여진 글이다.)

    그리하여 destroy 속성을 만들어 이벤트 리스너 또한 해제해주는 처리를 해야 GC가 수행되어진다고 한다.

    물론 GC뿐만 아니라 기본적으로 의미가 없어지는 순간 해제시켜야하는 건 당연하다.


    하지만 의외의 결과가 나왔다.

    leak.destory()를 주석처리해보았다.

    그렇다면 위의 말처럼 이벤트가 계속 일어나 GC가 수행되어서는 안된다.

    하지만 스냅샷을 통해 확인한 결과 GC가 수행되어있었다.


    그렇다면 GC를 믿고 메모리를 더더욱 신경 안써도 될만큼 개선이 되는 것인가?!

    2012년에 작성된 글이니 충분히 업데이트 되었을 가능성은 충분하다.


    이것이 100%는 아니다.

    원래 계속해서 개선되고 있다는 건 알지만, 개선된건지.. 뭐 잘못알고 있는지..

    그래도 많은 도움이 됬다. (나만..?)

    누군가 알고있다면 알려주길 바란다.


    자바스크립트 메모리 누수 관련 (영문)

    https://www.ibm.com/developerworks/web/library/wa-jsmemory/#ahs

    자바스크립트 메모리 누수 관련 (번역)

    http://jee1.tistory.com/862

    크롬 개발자 도구 관련

    http://kyunni22.tistory.com/7


    반응형

    댓글

Designed by Tistory.