Diagnozowanie opóźnień interfejsu użytkownika spowodowanych przez rozszerzenia
Gdy interfejs użytkownika staje się nieaktywny, program Visual Studio analizuje stos wywołań wątku interfejsu użytkownika, zaczynając od najniższego poziomu i postępując w kierunku podstawy. Jeśli program Visual Studio ustali, że ramka stosu wywołań należy do modułu będącego częścią zainstalowanego i włączonego rozszerzenia, zostanie wyświetlone powiadomienie.
Powiadomienie informuje użytkownika, że opóźnienie interfejsu użytkownika (czyli brak odpowiedzi w interfejsie użytkownika) mogło być wynikiem kodu z rozszerzenia. Udostępnia również użytkownikowi opcje wyłączania rozszerzenia lub przyszłych powiadomień dla tego rozszerzenia.
W tym dokumencie opisano, jak można zdiagnozować, co w kodzie rozszerzenia powoduje powiadomienia o opóźnieniach interfejsu użytkownika.
Notatka
Nie używaj wystąpienia eksperymentalnego programu Visual Studio do diagnozowania opóźnień interfejsu użytkownika. Niektóre części analizy stosu wywołań wymagane w przypadku powiadomień o opóźnieniu interfejsu użytkownika są wyłączone podczas korzystania z wystąpienia eksperymentalnego, co oznacza, że powiadomienia o opóźnieniu interfejsu użytkownika mogą nie być wyświetlane.
Omówienie procesu diagnostycznego jest następujące:
- Zidentyfikuj scenariusz wyzwalacza.
- Uruchom ponownie program VS z włączonym logowaniem aktywności.
- Uruchom śledzenie ETW.
- Wywołaj ponowne pojawienie się powiadomienia.
- Zatrzymaj śledzenie ETW.
- Sprawdź dziennik aktywności, aby uzyskać identyfikator opóźnienia.
- Przeanalizuj ślad ETW przy użyciu identyfikatora opóźnienia z kroku 6.
W poniższych sekcjach bardziej szczegółowo omówimy te kroki.
Identyfikowanie scenariusza wyzwalacza
Aby zdiagnozować opóźnienie interfejsu użytkownika, należy najpierw określić, co (sekwencja akcji) powoduje wyświetlenie powiadomienia w programie Visual Studio. Aby móc później wyzwolić powiadomienie z włączonym rejestrowaniem.
Uruchom ponownie VS z włączonym rejestrowaniem aktywności
Program Visual Studio może wygenerować "dziennik aktywności", który udostępnia informacje przydatne podczas debugowania problemu. Aby włączyć rejestrowanie aktywności w programie Visual Studio, otwórz program Visual Studio przy użyciu opcji wiersza polecenia /log
. Po uruchomieniu programu Visual Studio dziennik aktywności jest przechowywany w następującej lokalizacji:
%APPDATA%\Microsoft\VisualStudio\<vs_instance_id>\ActivityLog.xml
Aby dowiedzieć się więcej na temat znajdowania identyfikatora wystąpienia programu Visual Studio, zobacz narzędzia do wykrywania wystąpień programu Visual Studio i zarządzania nimi. Użyjemy tego dziennika aktywności później, aby dowiedzieć się więcej o opóźnieniach interfejsu użytkownika i powiązanych powiadomieniach.
Uruchamianie śledzenia ETW
Aby zebrać ślad ETW, można użyć PerfView. Narzędzie PerfView zapewnia łatwy w użyciu interfejs zarówno do zbierania śladu ETW, jak i analizowania go. Użyj następującego polecenia, aby zebrać ślad:
Perfview.exe collect C:\trace.etl /BufferSizeMB=1024 -CircularMB:2048 -Merge:true -Providers:*Microsoft-VisualStudio:@StacksEnabled=true -NoV2Rundown /kernelEvents=default+FileIOInit+ContextSwitch+Dispatcher
Umożliwia to dostawcę "Microsoft-VisualStudio", którego używa Visual Studio do zdarzeń związanych z powiadomieniami o opóźnieniach UI. Określa również słowo kluczowe dla dostawcy jądra, którego narzędzie PerfView może użyć do wygenerowania stosów czasu wątku widoku.
Wyzwól ponownie pojawienie się powiadomienia
Po uruchomieniu zbierania śladów narzędzia PerfView możesz użyć sekwencji akcji wyzwalacza (z kroku 1), aby powiadomienie było wyświetlane ponownie. Po wyświetlaniu powiadomienia można zatrzymać zbieranie śladów dla programu PerfView w celu przetworzenia i wygenerowania pliku śledzenia danych wyjściowych.
Zatrzymaj śledzenie ETW
Aby zatrzymać zbieranie śladów, wystarczy użyć przycisku Zatrzymaj zbieranie w oknie narzędzia PerfView. Po zatrzymaniu śledzenia program PerfView automatycznie przetworzy zdarzenia ETW i wygeneruje plik wyjściowy ze śledzenia.
Sprawdź dziennik aktywności, aby uzyskać identyfikator opóźnienia
Jak wspomniano wcześniej, dziennik aktywności można znaleźć w %APPDATA%\Microsoft\VisualStudio<vs_instance_id>\ActivityLog.xml. Za każdym razem, gdy Visual Studio wykrywa opóźnienie interfejsu użytkownika rozszerzenia, zapisuje węzeł w dzienniku aktywności i oznacza je jako źródło UIDelayNotifications
. Ten węzeł zawiera cztery informacje o opóźnieniu interfejsu użytkownika:
- Identyfikator opóźnienia interfejsu użytkownika, numer sekwencyjny, który jednoznacznie identyfikuje opóźnienie interfejsu użytkownika w sesji programu VS
- Identyfikator sesji, który jednoznacznie identyfikuje sesję programu Visual Studio od początku do zamknięcia
- Określa, czy dla opóźnienia interfejsu użytkownika zostało wyświetlone powiadomienie
- Rozszerzenie, które prawdopodobnie spowodowało opóźnienie interfejsu użytkownika
<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>
Notatka
Nie wszystkie opóźnienia interfejsu użytkownika powodują powiadomienie. Z tego powodu zawsze należy sprawdzić, czy powiadomienie jest wyświetlane, oraz wartość, aby poprawnie zidentyfikować prawidłowe opóźnienie interfejsu użytkownika.
Po znalezieniu poprawnego opóźnienia interfejsu użytkownika w dzienniku aktywności zapisz identyfikator opóźnienia interfejsu użytkownika określony w węźle. Użyjesz identyfikatora, aby wyszukać odpowiednie zdarzenie ETW w następnym kroku.
Analiza śladu ETW
Następnie otwórz plik śledzenia. Można to zrobić przy użyciu tego samego wystąpienia programu PerfView lub przez uruchomienie nowego wystąpienia programu PerfView i ustawienie bieżącej ścieżki folderu w lewym górnym rogu okna na lokalizację pliku śledzenia.
Następnie wybierz plik śledzenia w okienku po lewej stronie i otwórz go, wybierając pozycję Otwórz z menu kontekstowego lub prawym przyciskiem myszy.
Notatka
Domyślnie narzędzie PerfView generuje archiwum Zip. Po otwarciu trace.zipprogram automatycznie dekompresuje archiwum i otwiera ślad. Możesz to pominąć, usuwając zaznaczenie pola Zip podczas zbierania danych śledzenia. Jeśli jednak planujesz przenosić i używać śladów na różnych maszynach, zdecydowanie zalecamy, aby nie usuwać zaznaczenia pola Zip. Bez tej opcji wymagane pliki PDB dla zestawów Ngen nie będą towarzyszyć śladowi, a tym samym symbole z zestawów Ngen nie zostaną rozpoznane na maszynie docelowej. (Zobacz ten wpis na blogu, aby uzyskać więcej informacji na temat plików PDB dla zestawów Ngen).
Przetworzenie i otwarcie śladu za pomocą narzędzia PerfView może potrwać kilka minut. Po otwarciu śladu zostanie wyświetlona lista różnych "widoków".
widok podsumowania śledzenia PerfView
Najpierw użyjemy widoku Events, aby uzyskać zakres czasu opóźnienia interfejsu użytkownika:
- Otwórz widok Zdarzenia, wybierając węzeł
Events
pod śladem i wybierając pozycję Otwórz z menu kontekstowego lub prawym przyciskiem myszy. - Wybierz pozycję "
Microsoft-VisualStudio/ExtensionUIUnresponsiveness
" w okienku po lewej stronie. - Naciśnij Enter
Zastosowano wybór, a wszystkie zdarzenia ExtensionUIUnresponsiveness
są wyświetlane w okienku po prawej stronie.
Każdy wiersz w okienku po prawej stronie odpowiada opóźnieniu interfejsu użytkownika. Zdarzenie zawiera wartość "Identyfikator opóźnienia", która powinna być zgodna z identyfikatorem opóźnienia w dzienniku aktywności z kroku 6. Ponieważ ExtensionUIUnresponsiveness
jest wywoływany na końcu opóźnienia interfejsu użytkownika, znacznik czasu zdarzenia (w przybliżeniu) wskazuje czas zakończenia opóźnienia interfejsu użytkownika. Zdarzenie zawiera również czas trwania opóźnienia. Czas trwania można odjąć od znacznika czasu zakończenia, aby uzyskać znacznik czasu rozpoczęcia opóźnienia interfejsu użytkownika.
Na poprzednim zrzucie ekranu na przykład znacznik czasu zdarzenia wynosi 12 125,679, a czas trwania opóźnienia to 6143,085 (ms). Więc
- Rozpoczęcie opóźnienia wynosi 12 125,679 – 6,143,085 = 5982,594.
- Zakres czasu opóźnienia interfejsu użytkownika wynosi od 5982,594 do 12 125,679.
Gdy mamy zakres czasu, możemy zamknąć widok Zdarzenia i otworzyć widok Stosy czasu wątku (z działaniami StartStop). Ten widok jest szczególnie przydatny, ponieważ często rozszerzenia, które blokują wątek interfejsu użytkownika, tylko czekają na inne wątki lub operację związaną z we/wy. W związku z tym widok stosu procesora CPU, który jest opcją go-to w większości przypadków, może nie przechwytywać czasu, przez jaki wątek spędza blokadę, ponieważ nie używa procesora CPU w tym czasie. Stosy czasu wątku rozwiązują ten problem, prawidłowo wyświetlając zablokowany czas.
Podczas otwierania widoku stosów czasu wątków, wybierz proces , aby rozpocząć analizę.
widok stosów czasu wątku
W widoku Stosy czasu wątku w lewym górnym rogu strony można ustawić zakres czasu na wartości obliczone w poprzednim kroku i nacisnąć Enter, aby stosy były dostosowane do tego zakresu czasu.
Notatka
Określenie, który wątek jest wątkiem interfejsu użytkownika (wątek startowy), może być nieintuicyjne, jeśli zbieranie śladu jest uruchamiane po otwarciu programu Visual Studio. Jednak pierwsze elementy na stosie wątku interfejsu użytkownika (uruchamiania) są najprawdopodobniej zawsze bibliotekami DLL systemu operacyjnego (ntdll.dll i kernel32.dll), a następnie devenv!?
, a następnie msenv!?
. Ta sekwencja może pomóc zidentyfikować wątek interfejsu użytkownika.
Możesz również dodatkowo filtrować ten widok, uwzględniając tylko stosy zawierające moduły z pakietu.
- Ustaw GroupPats na pusty tekst, aby usunąć wszystkie dodane domyślnie grupy.
- Ustaw IncPats, aby oprócz istniejącego filtru procesu uwzględnić także część nazwy zestawu. W tym przypadku powinno to być devenv; UIDelayR2.
Narzędzie PerfView zawiera szczegółowe wskazówki w menu Pomoc, których można użyć do identyfikowania wąskich gardeł wydajności w kodzie. Ponadto poniższe linki zawierają więcej informacji na temat korzystania z interfejsów API wątkowych programu Visual Studio w celu zoptymalizowania kodu:
https://github.com/Microsoft/vs-threading/blob/main/doc/index.md
https://github.com/Microsoft/vs-threading/blob/main/doc/cookbook_vs.md
Możesz również użyć nowych analizatorów statycznych programu Visual Studio dla rozszerzeń (pakiet NuGet tutaj), które zawierają wskazówki dotyczące najlepszych rozwiązań dotyczących pisania wydajnych rozszerzeń. Zobacz listę analizatorów VSSDK i analizatorów wątków .
Notatka
Jeśli nie możesz rozwiązać problemu z brakiem odpowiedzi ze względu na zależności, nad którym nie masz kontroli (na przykład jeśli rozszerzenie musi wywoływać synchroniczne usługi VS w wątku interfejsu użytkownika), chcielibyśmy o tym wiedzieć. Jeśli jesteś członkiem programu Visual Studio Partner, możesz skontaktować się z nami, przesyłając wniosek o pomoc techniczną dla deweloperów. W przeciwnym razie użyj narzędzia "Zgłoś problem", aby przesłać swoją opinię i dołączyć "Extension UI Delay Notifications"
w tytule. Dołącz również szczegółowy opis analizy.