Chrome과 DevTools를 사용하여 페이지 성능에 영향을 미치는 메모리 문제를 찾는 방법을 알아보세요. 메모리 누수, 메모리 팽창 및 잦은 가비지 컬렉션 등의 문제를 예방할 수 있습니다
요약
- Chrome 작업 관리자를 사용하여 현재 페이지에서 사용 중인 메모리의 양을 확인하세요.
- 타임라인 기록으로 시간 경과에 따른 메모리 사용량을 시각화합니다.
- 분리된 DOM 트리 (일반적인 메모리 누수 원인)를 힙 스냅샷으로 식별할 수 있습니다.
- 할당 타임라인 기록을 사용하여 JS 힙에 새 메모리가 할당되는 시기를 알아낼 수 있습니다.
개요
RAIL 성능 모델에 중점을 두고 성능 노력의 초점을 얻는 것입니다
메모리 문제는 사용자가 인지할 수 있는 경우가 많기 때문에 중요합니다. 사용자가 메모리를 인지할 수 있음 다음과 같은 방법으로 문제를 해결합니다.
- 페이지 성능이 시간이 지남에 따라 점점 악화됩니다. 이는 아마도 메모리 누수가 발생합니다 메모리 누수는 페이지의 버그로 인해 페이지가 점진적으로 더 많이 사용되어 더 많아질 수 있습니다
- 페이지의 성능이 일관적으로 좋지 않습니다. 이는 아마도 메모리 팽창의 징후일 수 있습니다. 메모리 블로트는 페이지에서 최적의 페이지 속도를 위해 필요한 것보다 많은 메모리를 사용하는 것을 말합니다.
- 페이지의 성능이 지연되거나 자주 일시중지되는 것 같습니다. 이는 아마도 가비지 컬렉션을 해야 하기 때문입니다. 가비지 컬렉션은 브라우저가 메모리를 회수하는 것을 말합니다. 브라우저 결정할 수 있습니다. 수집 중에는 모든 스크립트 실행이 일시중지됩니다. 브라우저가 가비지 수집이 많아지면 스크립트 실행이 많이 일시 중지될 것입니다.
메모리 팽창: '너무 많은' 양은 얼마일까요?
메모리 누수는 쉽게 정의할 수 있습니다. 사이트에서 점점 더 많은 메모리를 사용하고 있다면 누수가 있습니다. 하지만 메모리 팽창은 정확히 파악하기가 조금 더 어렵습니다. '메모리를 너무 많이 사용'하는 경우의 조건은 무엇인가요?
기기와 브라우저에 따라 기능이 다르기 때문에 여기에는 엄격한 숫자가 없습니다. 고급형 스마트폰에서는 원활하게 실행되는 페이지가 저사양 스마트폰에서는 다운될 수 있습니다.
여기서 핵심은 RAIL 모델을 사용하여 사용자에게 집중하는 것입니다. 인기 있는 기기 알아보기 해당 기기에서 페이지를 테스트해 보세요. 사용 환경이 지속적으로 이어지는 경우 페이지가 해당 기기의 메모리 용량을 초과하는 것일 수 있습니다.
Chrome 작업 관리자로 메모리 사용량을 실시간으로 모니터링하세요
Chrome 작업 관리자를 사용하여 메모리 문제를 조사합니다. 작업 관리자 페이지가 현재 사용 중인 메모리의 양을 알려주는 실시간 모니터입니다.
Shift+Esc를 누르거나 Chrome 기본 메뉴로 이동하여 도구 더보기 > 작업 관리자에서 다음을 사용 작업 관리자를 엽니다.
작업 관리자의 표 헤더를 마우스 오른쪽 버튼으로 클릭하고 JavaScript 메모리를 사용 설정합니다.
다음 두 열을 통해 페이지가 메모리를 어떻게 사용하고 있는지 알 수 있습니다.
- Memory 열은 네이티브 메모리를 나타냅니다. DOM 노드는 네이티브 메모리에 저장됩니다. 만약 증가하면 DOM 노드가 생성되고 있다는 것을 알 수 있습니다.
- JavaScript 메모리 열은 JS 힙을 나타냅니다. 이 열에는 두 개의 값이 포함됩니다. 이 라이브 번호 (괄호 안의 숫자)입니다. 현재 전화번호 페이지에서 연결 가능한 객체가 사용 중인 메모리의 양을 나타냅니다. 이 번호가 새 객체가 생성되거나 기존 객체가 증가한다는 것을 의미합니다.
성능 기록으로 메모리 누수 시각화
성능 패널을 조사의 또 다른 시작점으로 사용할 수도 있습니다. 성능 패널을 사용하면 시간 경과에 따른 페이지의 메모리 사용량을 시각화할 수 있습니다.
- DevTools에서 Performance 패널을 엽니다.
- 메모리 체크박스를 사용 설정합니다.
- 녹화:
성능 메모리 기록을 시연하려면 아래 코드를 사용하는 것이 좋습니다.
var x = [];
function grow() {
for (var i = 0; i < 10000; i++) {
document.body.appendChild(document.createElement('div'));
}
x.push(new Array(1000000).join('x'));
}
document.getElementById('grow').addEventListener('click', grow);
코드에서 참조된 버튼을 누를 때마다 div
노드 수만 개가 추가됩니다.
100만 x
자(영문 기준)로 된 문자열이 x
배열로 푸시됩니다.
이 코드를 실행하면 다음 스크린샷과 같은 타임라인 기록이 생성됩니다.
먼저 사용자 인터페이스에 관한 설명입니다. 개요 창의 HEAP 그래프 (아래 NET)은 JS 힙을 나타냅니다. 개요 창 아래에는 카운터 창이 있습니다. 여기에서 다음 작업을 할 수 있습니다. JS 힙별로 분류된 메모리 사용량 확인 (Overview 창의 HEAP 그래프와 동일함). 문서, DOM 노드, 리스너 및 GPU 메모리를 기반으로 합니다. 체크박스를 사용 중지하면 그래프에서 체크박스가 숨겨집니다.
이제 코드를 스크린샷과 비교하여 분석해 보겠습니다. 노드 카운터(
코드와 정확하게 일치하는 것을 확인할 수 있습니다. 노드 수는
단계를 거칩니다. 노드 수가 증가할 때마다 grow()
를 호출한다고 가정할 수 있습니다. JS
힙 그래프 (파란색 그래프)는 그리 간단하지 않습니다. 권장사항에 따르면 첫 번째 하락 구간은
실제로는 강제 가비지 컬렉션입니다 (collect garbage 버튼을 누르면 실행됨). 따라서
JS 힙 크기가 급증하는 것을 볼 수 있습니다. 이는 자연스럽고 예상되는 일입니다.
JavaScript 코드는 버튼을 클릭할 때마다 DOM 노드를 생성하고
100만 자로 된 문자열을 만듭니다. 여기서 중요한 점은 JS 힙이
더 높습니다 (여기서 '시작'은 강제 가비지 컬렉션 이후의 지점임). 포함
실제로 JS 힙 크기나 노드 크기가 증가하는 패턴을 보면
메모리 누수를 의미할 수 있습니다
힙 스냅샷으로 분리된 DOM 트리 메모리 누수 발견
DOM 노드는 페이지의 DOM 트리 또는 자바스크립트 코드 노드를 '분리되었다'고 합니다. DOM 트리에서 삭제되지만 일부 JavaScript는 여전히 그것을 참조합니다. 분리된 DOM 노드는 메모리 누수의 일반적인 원인입니다. 이 섹션에서는 DevTools 사용 방법을 설명합니다. 분리된 노드를 식별하는 힙 프로파일러
다음은 분리된 DOM 노드의 간단한 예입니다.
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);
코드에서 참조된 버튼을 클릭하면 10개의 li
하위 요소가 있는 ul
노드가 생성됩니다. 이러한 노드
코드에서 참조되지만 DOM 트리에 없으므로 분리됩니다.
힙 스냅샷은 분리된 노드를 식별하는 한 가지 방법입니다. 이름에서 알 수 있듯이 힙 스냅샷은 페이지의 JS 객체 및 DOM 노드 간에 메모리가 분산되는 방식을 정의합니다. 스냅샷입니다.
스냅샷을 생성하려면 DevTools를 열고 Memory(메모리) 패널로 이동한 다음 Heap(힙) 스냅샷 라디오 버튼을 클릭한 다음 스냅샷 촬영 버튼을 누릅니다.
스냅샷을 처리하고 로드하는 데 다소 시간이 걸릴 수 있습니다. 완료되면 왼쪽에서 선택하세요. 패널 (이름: HEAP SNAPSHOTS)으로 표시됩니다.
클래스 필터 텍스트 상자에 Detached
를 입력하여 분리된 DOM 트리를 검색합니다.
캐럿을 확장하여 분리된 트리를 조사합니다.
노란색으로 강조표시된 노드는 JavaScript 코드에서 직접 참조하는 노드입니다. 노드 강조표시됨 직접 언급하지 않았습니다. 그들은 노란색 노드의 일부이기 때문에 살아있기만 합니다. 있습니다. 일반적으로 노란색 노드에 초점을 맞추는 것이 좋습니다. 노란색 노드가 표시되지 않도록 필요 이상으로 오래 살아있으며, 방사선의 일부인 빨간색 노드도 제거하고 표시됩니다.
노란색 노드를 클릭하여 더 자세히 조사하세요. 객체 창에서는 Kubernetes 객체
해당 정보를 참조하는 코드에 대한 정보를 제공합니다. 예를 들어 아래 스크린샷에서
detachedTree
변수가 노드를 참조하는지 확인합니다. 이 특정 메모리 누수를 해결하려면
detachedTree
를 사용하는 코드를 연구하고 노드에 대한 참조를 삭제합니다.
리소스를 삭제할 수 있습니다
할당 타임라인으로 JS 힙 메모리 누수 식별
Allocation Timeline은 JS 힙에서 메모리 누수를 추적하는 데 도움이 되는 또 다른 도구입니다.
Allocation Timeline을 시연하려면 다음 코드를 생각해 보세요.
var x = [];
function grow() {
x.push(new Array(1000000).join('x'));
}
document.getElementById('grow').addEventListener('click', grow);
코드에서 참조된 버튼을 누를 때마다 100만 자로 된 문자열이
x
배열에 추가되었습니다.
Allocation Timeline을 기록하려면 DevTools를 열고 Profiles 패널로 이동한 다음 Record
Allocation Timeline 라디오 버튼을 클릭하고 Start 버튼을 누른 다음 의심스러운 작업을 실행합니다.
메모리 누수를 발생시킨 다음 녹화 중지 버튼을 누르세요.
() 다음 경우
완료되었습니다.
녹화하면서 다음과 같이 Allocation Timeline에 확인할 수 있습니다.
이 파란색 막대는 새 메모리 할당을 나타냅니다. 이러한 새 메모리 할당이 후보입니다 메모리 누수를 줄일 수 있습니다 막대를 확대하여 생성자 창을 필터링하면 할당된 기간 동안 할당된 인벤토리 수입니다.
객체를 펼치고 값을 클릭하면 Object 창에서 객체에 대한 자세한 내용을 볼 수 있습니다. 대상
아래 스크린샷에서 새로 할당된 객체의 세부정보를 확인하고
Window
범위의 x
변수에 할당된 것을 확인할 수 있습니다.
함수별 메모리 할당 조사
Memory 패널에서 Allocation Sampling 유형을 사용하여 JavaScript 함수별 메모리 할당을 확인합니다.
- 할당 샘플링 라디오 버튼을 선택합니다. 페이지에 작업자가 있는 경우 Start(시작) 버튼 옆에 있는 드롭다운 메뉴를 사용하여 이를 프로파일링 대상으로 선택할 수 있습니다.
- Start(시작) 버튼을 누릅니다.
- 조사하려는 페이지에서 작업을 수행합니다.
- 모든 작업을 마치면 중지 버튼을 누릅니다.
DevTools에 기능별 메모리 할당 분석 결과가 표시됩니다. 기본 보기는 높음 (하단)입니다. Up): 메모리를 가장 많이 할당한 함수가 상단에 표시됩니다.
빈번한 가비지 컬렉션 찾기
페이지가 자주 일시중지되는 것 같다면 가비지 컬렉션 문제일 수 있습니다.
Chrome 작업 관리자 또는 타임라인 메모리 기록을 사용하여 자주 발생하는 가비지를 발견할 수 있습니다. 컬렉션입니다. 작업 관리자에서 메모리 또는 자바스크립트 메모리가 자주 오르내림 값은 빈번한 가비지 컬렉션을 나타냅니다. 타임라인 기록에서 자주 상승 및 하락함 JS 힙 또는 노드 수 그래프는 가비지 컬렉션이 잦은 것을 나타냅니다.
문제를 식별한 후에는 할당 타임라인 기록을 사용하여 어떤 함수가 할당의 원인이 되는지 파악할 수 있습니다.