확장으로 인해 발생한 진단 UI 지연
UI가 응답하지 않으면 Visual Studio가 UI 스레드의 호출 스택을 검사하고 리프부터 시작하여 베이스로 작업합니다. Visual Studio에서는 호출 스택 프레임이 설치되고 사용하도록 설정된 확장의 일부인 모듈에 속한다고 판단할 경우 알림을 표시합니다.
이 알림은 사용자에게 UI 지연(즉, 응답하지 않는 UI)이 확장 코드의 결과일 수 있음을 알립니다. 또한 확장을 사용하지 않거나 이 확장에 대한 이후 알림을 사용하지 않도록 설정하는 옵션도 제공합니다.
이 문서에서는 확장 코드에서 UI 지연 알림의 원인이 무엇인지 진단하는 방법을 설명합니다.
참고 항목
Visual Studio 실험 인스턴스를 사용하여 UI 지연을 진단하지 마세요. 실험 인스턴스를 사용할 때는 UI 지연 알림에 필요한 호출 스택 분석 중 일부가 해제되어 있으므로, UI 지연 알림이 표시되지 않을 수 있습니다.
진단 프로세스의 개요는 다음과 같습니다.
- 트리거 시나리오를 식별합니다.
- 활동 로그를 사용하도록 설정하여 VS를 다시 시작합니다.
- ETW 추적을 시작합니다.
- 알림이 다시 표시되도록 트리거합니다.
- ETW 추적을 중지합니다.
- 활동 로그를 검사하여 지연 ID를 가져옵니다.
- 6단계의 지연 ID를 사용하여 ETW 추적을 분석합니다.
다음 섹션에서는 이러한 단계를 더 자세히 살펴보겠습니다.
트리거 시나리오 식별
UI 지연 진단을 수행하기 위해서는 먼저 Visual Studio에서 알림이 표시되는 원인(작업 시퀀스)이 무엇인지 확인해야 합니다. 이것은 나중에 로그를 사용하도록 설정하여 알림을 트리거하기 위해 필요합니다.
활동 로그를 사용하도록 설정하여 VS 다시 시작
Visual Studio는 문제를 디버그할 때 유용한 정보를 제공하는 “활동 로그”를 생성할 수 있습니다. Visual Studio에서 활동 로그를 사용하도록 설정하려면 /log
명령줄 옵션을 사용하여 Visual Studio를 엽니다. Visual Studio가 시작되면 활동 로그가 다음 위치에 저장됩니다.
%APPDATA%\Microsoft\VisualStudio\<vs_instance_id>\ActivityLog.xml
VS 인스턴스 ID를 찾는 방법에 대한 자세한 내용은 Visual Studio 인스턴스 검색 및 관리 도구를 참조하세요. 이 활동 로그는 나중에 UI 지연 및 관련 알림에 대한 자세한 정보를 확인하기 위해 사용됩니다.
ETW 추적 시작
PerfView를 사용하여 ETW 추적을 수집할 수 있습니다. PerfView는 ETW 추적 수집 및 분석 모두에 쉽게 사용할 수 있는 인터페이스를 제공합니다. 다음 명령을 사용하여 추적을 수집합니다.
Perfview.exe collect C:\trace.etl /BufferSizeMB=1024 -CircularMB:2048 -Merge:true -Providers:*Microsoft-VisualStudio:@StacksEnabled=true -NoV2Rundown /kernelEvents=default+FileIOInit+ContextSwitch+Dispatcher
이렇게 하면 Visual Studio가 UI 지연 알림과 관련된 이벤트에 사용하는 공급자인 "Microsoft-VisualStudio" 공급자가 사용하도록 설정됩니다. 또한 PerfView가 스레드 시간 스택 보기를 생성하기 위해 사용할 수 있는 커널 공급자의 키워드를 지정합니다.
알림이 다시 표시되도록 트리거합니다.
PerfView에서 추적 수집이 시작되면 알림이 다시 표시되도록 트리거 작업 시퀀스(1단계 참조)를 사용할 수 있습니다. 알림이 표시되면 PerfView가 출력 추적 파일을 처리하고 생성하도록 추적 수집을 중지할 수 있습니다.
ETW 추적 중지
추적 수집을 중지하려면 단순히 PerfView 창에서 수집 중지 단추를 사용합니다. 추적 수집을 중지하면 PerfView가 ETW 이벤트를 자동으로 처리하고 출력 추적 파일을 생성합니다.
활동 로그를 검사하여 지연 ID를 가져옵니다.
앞에서 설명한 것처럼 활동 로그는 %APPDATA%\Microsoft\VisualStudio<vs_instance_id>\ActivityLog.xml에서 찾을 수 있습니다. Visual Studio에서 확장 UI 지연이 검색될 때마다 UIDelayNotifications
를 원본으로 사용해서 활동 로그에 노드를 기록합니다. 이 노드에는 UI 지연에 대한 네 가지 정보가 포함되어 있습니다.
- VS 세션에서 UI 지연을 고유하게 식별하는 순차 번호인 UI 지연 ID
- 시작부터 닫기까지 Visual Studio 세션을 고유하게 식별하는 세션 ID
- 알림이 UI 지연에 대해 표시되었는지 여부
- UI 지연을 발생시켰을 수 있는 확장
<entry>
<record>271</record>
<time>2018/02/03 12:02:52.867</time>
<type>Information</type>
<source>UIDelayNotifications</source>
<description>A UI delay (Delay ID = 0) has been detected. (Session ID=16e49d4b-26c2-4247-ad1c-488edeb185e0; Blamed extension="UIDelayR2"; Notification shown? Yes.)</description>
</entry>
참고 항목
모든 UI 지연으로 인해 알림이 발생하지는 않습니다. 따라서 UI 지연을 올바르게 식별하기 위해서는 항상 알림 표시? 값을 확인해야 합니다.
활동 로그에서 올바른 UI 지연을 찾은 후 노드에 지정된 UI 지연 ID를 적어 둡니다. 다음 단계에서 해당 ETW 이벤트를 찾으려면 이 ID를 사용해야 합니다.
ETW 추적 분석
그런 다음, 추적 파일을 엽니다. 이 작업은 동일한 PerfView 인스턴스를 사용해서 또는 새 인스턴스를 시작하고 창 왼쪽 위에서 현재 폴더 경로를 추적 파일 위치로 설정해서 수행할 수 있습니다.
그런 다음, 왼쪽 창에서 추적 파일을 선택하고 마우스 오른쪽 단추 클릭 또는 바로 가기 메뉴에서 열기를 선택하여 엽니다.
참고 항목
기본적으로 PerfView는 Zip 보관 파일을 출력합니다. trace.zip을 열면 자동으로 보관 파일의 압축이 풀리고 추적이 열립니다. 추적 수집 중 Zip 상자를 선택 해제하면 이를 건너뛸 수 있습니다. 그러나 서로 다른 컴퓨터 간에 추적을 전송하고 사용하려면 Zip 상자를 선택 해제하지 않는 것이 좋습니다. 이 옵션을 선택하지 않으면 Ngen 어셈블리에 필요한 PDB가 추적에 포함되지 않으므로, Ngen 어셈블리의 기호가 대상 컴퓨터에서 확인되지 않습니다. (Ngen 어셈블리의 PDB에 대한 자세한 내용은 이 블로그 게시물을 참조하세요.)
PerfView가 추적을 처리하고 여는 데 몇 분 정도 걸릴 수 있습니다. 추적이 열리면 여러 “보기” 목록이 아래에 표시됩니다.
먼저 이벤트 보기를 사용하여 UI 지연의 시간 범위를 가져옵니다.
- 추적 아래에서
Events
노드를 선택하고 마우스 오른쪽 단추 클릭 또는 바로 가기 메뉴에서 열기를 선택하여 이벤트 보기를 엽니다. - 왼쪽 창에서 “
Microsoft-VisualStudio/ExtensionUIUnresponsiveness
”를 선택합니다. - Enter 키를 누릅니다.
선택 항목이 적용되고 모든 ExtensionUIUnresponsiveness
이벤트가 오른쪽 창에 표시됩니다.
오른쪽 창의 각 행이 UI 지연에 해당합니다. 이벤트에는 6단계의 활동 로그에 있는 지연 ID와 일치하는 “지연 ID” 값이 포함됩니다. UI 지연이 끝날 때 ExtensionUIUnresponsiveness
가 발생하므로, 이벤트의 타임스탬프에 UI 지연의 종료 시간이 대략적으로 표시됩니다. 이벤트에는 또한 지연 기간도 포함됩니다. 종료 타임스탬프에서 기간을 빼면 UI 지연이 시작된 시간에 대한 타임스탬프를 얻을 수 있습니다.
예를 들어 이전 스크린샷에서 이벤트 타임스탬프는 12,125.679이고 지연 기간은 6,143.085(밀리초)입니다. 그러므로
- 지연 시작은 12,125.679 - 6,143.085 = 5,982.594입니다.
- UI 지연 시간 범위는 5,982.594에서 12,125.679까지입니다.
시간 범위가 확인되었으면 이벤트 보기를 닫고 스레드 시간(StartStop 작업 포함) 스택 보기를 열 수 있습니다. UI 스레드를 차단하는 확장이 단순히 다른 스레드 또는 I/O 바인딩 작업을 기다리기 때문에 이 보기가 특히 유용합니다. 따라서 대부분의 경우에 적합한 옵션인 CPU 스택 보기는 해당 시간 동안 CPU를 사용하지 않기 때문에 스레드가 차단에 사용하는 시간을 캡처하지 못할 수 있습니다. 스레드 시간 스택은 차단된 시간을 적절하게 표시하여 이 문제를 해결합니다.
스레드 시간 스택 보기를 열 때 분석을 시작하기 위해 devenv 프로세스를 선택합니다.
스레드 시간 스택 보기의 페이지 왼쪽 위에서 이전 단계에서 계산한 값으로 시간 범위를 설정할 수 있습니다. 스택이 해당 시간 범위로 조정되도록 Enter 키를 누릅니다.
참고 항목
Visual Studio가 이미 열린 후 추적 수집이 시작되는 경우에는 UI(시작) 스레드인 스레드를 확인하는 것이 직관적이지 않을 수 있습니다. 그러나 UI(시작) 스레드의 첫 번째 요소는 항상 devenv!?
및 msenv!?
이 뒤에 오는 운영 체제 DLL(ntdll.dll 및 kernel32.dll)일 가능성이 높습니다. 이 시퀀스는 UI 스레드를 식별하는 데 도움이 될 수 있습니다.
또한 패키지 모듈이 포함된 스택만 포함하여 이 보기를 추가로 필터링할 수 있습니다.
- GroupPats를 빈 텍스트로 설정하여 기본적으로 추가되는 그룹화를 제거합니다.
- 기존 프로세스 필터 외에도 어셈블리 이름 부분을 포함하도록 IncPats를 설정합니다. 이 경우에는 devenv;UIDelayR2여야 합니다.
PerfView에는 도움말 메뉴 아래에 코드에서 성능 병목 지점을 식별하는 데 사용할 수 있는 자세한 지침이 있습니다. 또한 다음 링크는 Visual Studio 스레딩 API를 사용하여 코드를 최적화하는 방법에 대한 자세한 정보를 제공합니다.
https://github.com/Microsoft/vs-threading/blob/master/doc/index.md
https://github.com/Microsoft/vs-threading/blob/master/doc/cookbook_vs.md
또한 효율적인 확장 작성을 위해 모범 사례 안내를 제공하는 새로운 확장용 Visual Studio 정적 분석기(여기의 NuGet 패키지)를 사용할 수 있습니다. VSSDK 분석기 및 스레딩 분석기 목록을 참조하세요.
참고 항목
확장이 UI 스레드에서 동기 VS 서비스를 호출해야 하는 경우와 같이 제어할 수 없는 종속 항목으로 인해 응답하지 않는 문제를 해결하기 어려운 경우가 있으면 저희에게 알려주시기 바랍니다. Visual Studio 파트너 프로그램의 멤버인 경우에는 개발자 지원 요청을 제출하여 문의할 수 있습니다. 그렇지 않으면 ‘문제 보고’ 도구를 사용하고 제목에 "Extension UI Delay Notifications"
를 포함하여 피드백을 제출하시기 바랍니다. 분석에 대한 자세한 설명도 포함하시기 바랍니다.