programing

Chrome에서 JavaScript 메모리 누수 찾기

muds 2023. 10. 13. 22:34
반응형

Chrome에서 JavaScript 메모리 누수 찾기

백본 보기를 만들고, 이벤트에 핸들러를 연결하고, 사용자 정의 클래스를 인스턴스화하는 매우 간단한 테스트 케이스를 만들었습니다.저는 이 샘플에서 "Remove" 버튼을 클릭하면 모든 것이 정리되고 메모리 누수가 없어야 한다고 생각합니다.

코드에 대한 jsfiddle이 여기 있습니다: http://jsfiddle.net/4QhR2/

// scope everything to a function
function main() {

    function MyWrapper() {
        this.element = null;
    }
    MyWrapper.prototype.set = function(elem) {
        this.element = elem;
    }
    MyWrapper.prototype.get = function() {
        return this.element;
    }

    var MyView = Backbone.View.extend({
        tagName : "div",
        id : "view",
        events : {
            "click #button" : "onButton",
        },    
        initialize : function(options) {        
            // done for demo purposes only, should be using templates
            this.html_text = "<input type='text' id='textbox' /><button id='button'>Remove</button>";        
            this.listenTo(this,"all",function(){console.log("Event: "+arguments[0]);});
        },
        render : function() {        
            this.$el.html(this.html_text);

            this.wrapper = new MyWrapper();
            this.wrapper.set(this.$("#textbox"));
            this.wrapper.get().val("placeholder");

            return this;
        },
        onButton : function() {
            // assume this gets .remove() called on subviews (if they existed)
            this.trigger("cleanup");
            this.remove();
        }
    });

    var view = new MyView();
    $("#content").append(view.render().el);
}

main();

하지만 구글 크롬의 프로파일러를 어떻게 사용해서 이것이 사실인지 확인할 수 있을지 모르겠습니다.힙 프로파일러 스냅샷에는 수많은 것들이 나타나는데, 저는 무엇이 좋은지 나쁜지 해독하는 방법을 모릅니다.지금까지 본 튜토리얼에서는 "스냅샷 프로파일러를 사용하라"고만 하거나, 전체 프로파일러가 어떻게 작동하는지에 대한 매우 상세한 선언문을 제공합니다.프로파일러를 도구로 사용하는 것이 가능합니까, 아니면 전체가 어떻게 설계되었는지 정말로 이해해야 합니까?

편집: 다음과 같은 튜토리얼:

Gmail 메모리 누수 수정

DevTools 사용

제가 본 바로는 더 강한 물질의 대표적인 것입니다.하지만 3가지 스냅샷 기법의 개념을 소개하는 것 외에도 실무적인 지식 측면에서는 거의 제공하지 못하고 있습니다(저와 같은 초보자에게는 말입니다.'데브툴 사용' 튜토리얼은 실제 예시를 통해 작동하지 않으므로 모호하고 일반적인 개념 설명은 크게 도움이 되지 않습니다.Gmail' 예에 관해서는 다음과 같습니다.

새는 곳을 찾으셨군요자 이제는 뭐죠?

  • 프로파일 패널의 하단 절반에서 누출된 물체의 고정 경로를 조사합니다.

  • 할당 사이트를 쉽게 추론할 수 없는 경우(즉, 이벤트 청취자):

  • JS 콘솔을 통해 유지 객체의 생성자에게 스택 추적을 할당에 저장하도록 계측합니다.

  • 클로저 사용?적절한 기존 플래그(예: gog.events)를 활성화합니다.청취자 여러분.ENABLE_MONITORING)을 사용하여 시공 중 creationStack 속성을 설정합니다.

나는 그 글을 읽고 난 후에 더 혼란스러워집니다.그리고 다시 말하지만, 그것은 나에게 일을 하라고 말하는 것이지, 그것을 어떻게 하라는 것은 아닙니다.제가 보기에 모든 정보는 너무 모호하거나 이미 그 과정을 이해한 사람에게만 의미가 있습니다.

아래 @Jonathan Naguin의 답변에서 이러한 보다 구체적인 문제가 제기되었습니다.

메모리 유출을 찾는 좋은 작업 흐름은 세 가지 스냅샷 기법인데, 이는 Loreena Lee와 Gmail 팀이 메모리 문제를 해결하기 위해 처음 사용한 것입니다.이 단계는 일반적으로 다음과 같습니다.

  • 힙 스냅샷을 만듭니다.
  • 뭘 좀 해봐요.
  • 힙 스냅샷을 하나 더 만듭니다.
  • 같은 말을 반복합니다.
  • 힙 스냅샷을 하나 더 만듭니다.
  • 스냅샷 3의 "요약" 보기에서 스냅샷 1과 2 사이에 할당된 개체를 필터링합니다.

예를 들어 시작 단추의 클릭 이벤트가 있을 때까지 Backbone View 생성을 지연시키는 이 프로세스(여기서 확인 가능)를 보여주도록 코드를 조정했습니다.지금:

  • HTML(이 주소를 사용하여 로컬로 저장)을 실행하고 스냅샷을 만듭니다.
  • 보기를 만들려면 시작을 클릭합니다.
  • 다른 스냅샷을 만듭니다.
  • 제거를 누릅니다.
  • 다른 스냅샷을 만듭니다.
  • 스냅샷 3의 "요약" 보기에서 스냅샷 1과 2 사이에 할당된 개체를 필터링합니다.

이제 메모리 유출을 찾을 준비가 되었군요!

몇 가지 다른 색상의 노드가 표시됩니다.Red 노드는 Javascript에서 직접 참조하지 않지만 분리된 DOM 트리의 일부이므로 활성화됩니다.트리에 Javascript에서 참조되는 노드가 있을 수 있지만(폐쇄 또는 변수로 사용될 수 있음), 공교롭게도 전체 DOM 트리가 가비지 수집되는 것을 방지하고 있습니다.

enter image description here

그러나 노란색 노드는 자바스크립트에서 직접적으로 참조됩니다.동일한 분리된 DOM 트리에서 노란색 노드를 찾아 Javascript에서 참조를 찾습니다.DOM 창에서 요소로 이어지는 일련의 속성이 있어야 합니다.

특히 빨간색으로 표시된 HTML Div 요소를 볼 수 있습니다.요소를 확장하면 "캐시" 함수가 참조하는 것을 볼 수 있습니다.

enter image description here

행을 선택하면 콘솔 유형 $0에 실제 기능과 위치가 표시됩니다.

>$0
function cache( key, value ) {
        // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
        if ( keys.push( key += " " ) > Expr.cacheLength ) {
            // Only keep the most recent entries
            delete cache[ keys.shift() ];
        }
        return (cache[ key ] = value);
    }                                                     jquery-2.0.2.js:1166

요소가 참조되는 곳입니다.유감스럽게도 당신이 할 수 있는 것은 많지 않습니다. jQuery의 내부 메커니즘입니다.그러나 테스트 목적으로만 기능을 실행하고 방법을 다음과 같이 변경합니다.

function cache( key, value ) {
    return value;
}

이제 이 과정을 반복하면 빨간색 노드가 보이지 않습니다. :)

설명서:

jsfiddle의 메모리 프로파일링에 대한 팁은 다음과 같습니다.다음 URL을 사용하여 jsfiddle 결과를 분리하면 jsfiddle 프레임워크를 모두 제거하고 결과만 로드합니다.

http://jsfiddle.net/4QhR2/show/

저는 다음 문서를 읽을 때까지 타임라인과 프로파일러를 사용하여 메모리 유출을 추적하는 방법을 전혀 파악할 수 없었습니다.'Object Allocation Tracker'란 제목의 섹션을 읽고 'Record Heap Allocations' 도구를 사용하여 일부 분리된 DOM 노드를 추적할 수 있었습니다.

jQuery 이벤트 바인딩에서 Backbone 이벤트 위임으로 전환하여 문제를 해결하였습니다.합니다를 으로 이벤트의 View.remove()중 실행해 보십시오.할 수 있습니다 일부 데모를 직접 실행해 보십시오. 이 데모들은 사용자가 식별할 수 있도록 메모리 누출로 설정되어 있습니다.이 문서를 공부한 후에도 이해가 안 된다면 여기서 자유롭게 질문하세요.

https://developers.google.com/chrome-developer-tools/docs/javascript-memory-profiling

기본적으로 힙 스냅샷 내부의 개체 수를 확인해야 합니다.두 스냅샷 사이에 개체 수가 증가하여 개체를 폐기한 경우에는 메모리 누수가 발생합니다.코드에서 분리되지 않는 이벤트 핸들러를 찾으라는 조언입니다.

구글의 소개 동영상이 있는데 자바스크립트 메모리 유출을 찾는 데 큰 도움이 될 것입니다.

https://www.youtube.com/watch?v=L3ugr9BJqIs

다음과 같은 내용을 읽을 수도 있습니다.

http://addyosmani.com/blog/taming-the-unicorn-easing-javascript-memory-profiling-in-devtools/

크롬 개발자 도구의 사용법을 설명하고 힙 스냅샷 비교 및 사용 가능한 다양한 힙 스냅샷 보기를 사용하여 메모리 누출을 확인하고 찾는 방법에 대한 단계별 조언을 제공합니다.

Chrome Developer 도구를 사용하여 메모리 누수를 식별하는 것과 관련된 몇 가지 중요한 참고 사항:

1) 크롬 자체는 비밀번호와 숫자 필드 같은 특정 요소에 대한 메모리 누수가 있습니다.https://bugs.chromium.org/p/chromium/issues/detail?id=967438 .분리된 요소를 검색할 때 힙 스냅샷을 오염시키므로 디버깅할 때는 이러한 스냅샷을 사용하지 마십시오.

2) 브라우저 콘솔에 기록하지 마십시오.Chrome은 콘솔에 기록된 오브젝트를 쓰레기 수집하지 않으므로 결과에 영향을 미칩니다.스크립트/페이지 시작 부분에 다음 코드를 배치하여 출력을 억제할 수 있습니다.

console.log = function() {};
console.warn = console.log;
console.error = console.log;

3) 힙 스냅샷을 사용하고 "detach"를 검색하여 분리된 DOM 요소를 식별합니다.객체를 호버링함으로써 idouter를 포함한 모든 속성에 액세스할 수 있습니다.각 요소를 식별하는 데 도움이 될 수 있는 HTML.Screenshot of JS Heap Snapshot with details about detached DOM element 분리된 요소가 여전히 너무 일반적이어서 인식할 수 없는 경우 테스트를 실행하기 전에 브라우저 콘솔을 사용하여 고유 ID를 할당합니다.

var divs = document.querySelectorAll("div");
for (var i = 0 ; i < divs.length ; i++)
{
    divs[i].id = divs[i].id || "AutoId_" + i;
}
divs = null; // Free memory

이제 분리된 요소를 식별하면 id=라고 가정합니다."AutoId_49", 페이지를 다시 로드하고 위의 토막글을 다시 실행한 후 id=로 요소 찾기"DOM 검사기 또는 문서를 사용하는 AutoId_49".querySelector(...) 페이지 내용이 예측 가능한 경우에만 작동합니다.

테스트를 실행하여 메모리 누출을 식별하는 방법

1) 페이지 로드(콘솔 출력이 억제된 상태에서!)

2) 메모리 누수를 초래할 수 있는 작업을 페이지에서 수행합니다.

3) 개발자 도구를 사용하여 힙 스냅샷을 만들고 "detach"를 검색합니다.

4) 요소를 이동하여 ID 또는 외부에서 식별HTML 속성

개발자 도구에서 타임라인 탭을 볼 수도 있습니다.앱의 사용량을 기록하고 DOM 노드 및 이벤트 청취자 수를 주시합니다.

메모리 그래프가 실제로 메모리 누출을 나타내는 경우 프로파일러를 사용하여 누출되는 내용을 파악할 수 있습니다.

두 번째로, 힙 스냅샷을 찍으라는 조언을 드립니다. 메모리 유출을 감지하는 데 탁월하고 크롬은 스냅샷 생성에 탁월합니다.

를 받기 는 '된 많은 웹 이러한 어떤 되지 않아 '' 으로를는합니다. 이러한 계층의 많은 부분은 UI에서 '삭제'될 것이지만 어떤 이유에서인지 메모리가 할당 해제되지 않았습니다.스냅샷 도구를 사용하여 JQuery가 객체에 대한 참조를 유지하고 있다는 것을 확인할 수 있었습니다(소스는 내가 a를 트리거하려고 할 때였습니다)..load()범위를 벗어났음에도 불구하고 참조를 유지한 이벤트).이 정보를 한 손으로 저장하면 다른 사람의 라이브러리를 사용할 때 매우 유용한 도구이며 GC가 작업을 수행하지 못하게 하는 참조가 남아 있습니다.

편집: 스냅샷 생성에 소요되는 시간을 최소화하기 위해 수행할 작업을 미리 계획하고, 문제의 원인이 무엇인지 가설을 세우고, 각 시나리오를 테스트하여 전후에 스냅샷을 만드는 것도 유용합니다.

2021년에 사용 가능한 툴과 함께 여기에 2센트를 추가합니다. https://yonatankra.com/how-to-profile-javascript-performance-in-the-browser/

여기 짧은 비디오 버전이 있습니다: https://yonatankra.com/detect-memory-leak-with-chrome-dev-tools

언급URL : https://stackoverflow.com/questions/19621074/finding-javascript-memory-leaks-with-chrome

반응형