연습: UI 응답성 개선(HTML)
이 연습에서는 HTML UI 응답성 프로파일러를 사용하여 간단한 성능 문제를 식별하고 수정하는 과정을 안내합니다. 프로파일러는 JavaScript를 사용하여 Windows용으로 작성된 Visual Studio for Windows 스토어 앱에서 사용할 수 있습니다. 이 시나리오에서는 DOM 요소를 너무 자주 업데이트하는 성능 테스트 앱을 만들고 프로파일러를 사용하여 이 문제를 식별 및 수정합니다.
성능 테스트 앱 만들기 및 실행
Visual Studio에서 파일, 새로 만들기, 프로젝트를 선택합니다.
왼쪽 창에서 JavaScript를 선택하고 Windows 스토어, Universal 또는 Windows Phone을 선택합니다.
중간 창에서 새 응용 프로그램 등의 빈 프로젝트 템플릿 중 하나를 선택합니다.
이름 상자에서 JS_Perf_Tester와 같은 이름을 지정한 후 확인을 선택합니다.
솔루션 탐색기에서 default.html을 열고 <body> 태그 사이에 다음 코드를 붙여넣습니다.
<div class="wrapper"> <button id="content">Waiting for values</button> </div>
default.css를 열고 다음 CSS 코드를 추가합니다.
#content { margin-left: 100px; margin-top: 100px; }
default.js를 열고 모든 코드를 이 코드로 바꿉니다.
(function () { "use strict"; var app = WinJS.Application; var activation = Windows.ApplicationModel.Activation; var content; var wrapper; app.onactivated = function (args) { if (args.detail.kind === activation.ActivationKind.launch) { if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { content = document.getElementById("content"); wrapper = document.querySelector(".wrapper"); content.addEventListener("click", handler); } else { } args.setPromise(WinJS.UI.processAll()); } }; app.oncheckpoint = function (args) { }; app.start(); var idx = 0; var count = 0; var max = 5000; var text = ["what", "is", "the", "Matrix?"]; var color = ["red", "crimson", "maroon", "purple"]; function increment() { setTimeout(function () { idx++; count++; if (idx > 3) { idx = 0; } if (count < max) { increment(); } }, 1000); } function setValues() { content = document.getElementById("content"); content.removeNode(true); var newNode = document.createElement("button"); newNode.id = "content"; newNode.textContent = text[idx]; //newNode.textContent = getData(); newNode.style.backgroundColor = color[idx]; //newNode.style.animationName = "move"; //count++; wrapper.appendChild(newNode); } function update() { setTimeout(function () { setValues(); if (count < max) { update(); } }); } function handler(args) { content.textContent = "eenie"; increment(); update(); } })();
F5 키를 선택하여 디버깅을 시작합니다. 페이지에 값 대기 단추가 나타나는지 확인합니다.
값 대기를 선택하고 약 1 초에 한 번씩 단추 텍스트 및 색상 업데이트를 확인합니다. 이것은 정상적인 현상입니다.
Alt+Tab을 눌러 Visual Studio로 다시 전환하고 Shift+F5를 눌러 디버깅을 중지합니다.
앱이 제대로 작동하는지 확인했으므로 프로파일러를 사용하여 성능을 검사할 수 있습니다.
성능 데이터 분석
디버그 도구 모음에 있는 디버깅 시작 목록에서 Windows Phone 에뮬레이터 또는 시뮬레이터 중 하나를 선택합니다.
팁
Windows 스토어 앱의 경우 이 목록에서 로컬 컴퓨터 또는 원격 컴퓨터를 선택할 수도 있습니다.그러나 에뮬레이터 또는 시뮬레이터를 사용하면 Visual Studio 옆에 두고 실행 중인 앱과 HTML UI 응답성 프로파일러 간을 쉽게 전환할 수 있습니다.자세한 내용은 Visual Studio에서 스토어 앱 실행 및 Visual Studio를 사용하여 원격 컴퓨터에서 Windows 스토어 앱 실행을 참조하십시오.
디버그 메뉴에서 성능 및 진단을 선택합니다.
사용 가능한 도구에서 HTML UI 응답성을 선택한 다음 시작을 선택합니다.
이 자습서에서는 시작 프로젝트에 프로파일러를 연결합니다. 설치된 앱에 프로파일러를 연결하는 등 기타 옵션에 대한 자세한 내용은 UI 응답성 분석(HTML)을 참조하십시오.
프로파일러를 시작하면 VsEtwCollector.exe 실행 권한을 요청하는 사용자 계정 컨트롤이 표시될 수 있습니다. 예를 선택합니다.
실행 중인 응용 프로그램의 경우 값 대기를 선택하고 약 10초 기다립니다. 약 1초에 한 번씩 단추 텍스트 및 색상 업데이트를 확인합니다.
Alt+Tab을 눌러 실행 중인 응용 프로그램에서 Visual Studio로 전환합니다.
수집 중지를 선택합니다.
Visual Studio 새 탭에 정보가 표시됩니다. CPU 사용률 및 시각적 처리량(FPS) 데이터를 보면 몇 가지 추세를 쉽게 식별할 수 있습니다.
값 대기 단추를 누르면 3초 후 CPU 사용률이 크게 증가하며 이 시점부터 이벤트의 명백한 패턴(스크립팅, 스타일 및 렌더링 이벤트의 일관성 있는 혼합)을 보여 줍니다.
시각적 처리량에 영향을 주지 않고 FPS의 처리량은 60으로 그대로 유지됩니다(즉, 프레임이 떨어지지 않음).
CPU 사용률 그래프의 일반적인 섹션에서 작업량이 많은 이 주기 동안 앱에서 무엇을 수행하는지 살펴보겠습니다.
CPU 사용률 그래프의 중간에서 첫 번째와 두 번째 부분을 선택합니다(클릭하여 끌기 기능을 사용하거나 누른 후 화살표 키 사용). 다음 그림에서는 선택 후의 CPU 사용률 그래프를 보여 줍니다. 공유되지 않은 영역이 선택 영역입니다.
확대를 선택합니다.
그래프에 선택한 기간이 더 자세히 표시됩니다. 다음 그림에서는 확대 후의 CPU 사용률 그래프를 보여 줍니다. 그래프의 특정 데이터가 다를 수는 있지만, 일반적인 패턴은 확인할 수 있습니다.
아래쪽 창의 시간 표시 막대 정보에 선택한 기간에 대한 세부 정보의 예제가 표시됩니다.
시간 표시 막대 정보의 이벤트에서 CPU 사용률 그래프의 시각적 추세를 확인합니다. 짧은 기간 동안 많은 이벤트가 발생합니다. 시간 표시 막대 정보 뷰에 Timer, Layout 및 Paint 이벤트가 표시됩니다.
컨텍스트 메뉴를 사용하거나 아래쪽 창에서 Timer 이벤트 중 하나를 오른쪽 단추로 클릭하고 이벤트 필터를 선택합니다. 다음 그림에서는 이 테스트 응용 프로그램의 Timer 이벤트 중 하나에 일반적으로 사용하는 세부 정보의 예제를 보여 줍니다.
데이터를 통해 다양한 정보를 수집할 수 있습니다. 예를 들면 다음과 같습니다.
스크립팅 이벤트로 식별하기 위해 색으로 구분된 각 Timer 이벤트에는 document.createElement에 대한 호출과 스타일 계산 및 style.backgroundColor와 appendChild()에 대한 호출이 포함됩니다.
선택한 약 1-2초 정도의 짧은 시간 동안 수많은 Timer, Layout 및 Paint 이벤트가 발생합니다. Timer 이벤트는 앱을 실행한 후 값 대기 단추를 선택할 때 시각적으로 표시되는 초당 한 번의 업데이트보다 훨씬 자주 발생합니다.
조사하려면 왼쪽 아래 창에서 Timer 이벤트 중 하나에 대한 익명 함수 링크를 선택합니다. 다음 함수는 default.js에서 열립니다.
function update() { setTimeout(function () { setValues(); if (count < max) { update(); } }); }
이 재귀 함수는 UI의 단추를 업데이트하는 setValues() 함수를 호출하는 루프를 설정합니다. 프로파일러에서 다른 타이머 이벤트를 검사해 이 코드에서 모든 또는 대부분의 타이머 이벤트 결과가 너무 자주 실행되어 여기서 문제가 발생하는 것처럼 나타난다는 사실을 발견했습니다.
성능 문제 해결
update() 함수를 다음 코드로 바꿉니다.
function update() { setTimeout(function () { setValues(); if (count < max) { update(); } }, 1000 ); }
이 수정된 버전의 코드에는 이전 버전의 코드에서 누락된 1000밀리초의 지연이 포함되어 있으므로 기본 지연 값이 사용됩니다. 프로파일러 데이터에서 기본값은 0밀리초로 표시되는데, 이 때문에 setValues() 기능이 너무 자주 실행됩니다.
HTML UI 응답성 프로파일러를 다시 실행하고 CPU 사용률 그래프를 확인합니다. 과도한 이벤트가 사라지고 CPU 사용률이 0 가까이 떨어진 것을 알 수 있습니다. 수정된 것입니다.