Rozwiązywanie problemów z wpływem pliku nagłówka na czas kompilacji
Użyj widoków uwzględnionych plików usługi Build Insights i uwzględnij drzewa, aby rozwiązać problemy z wpływem #include
plików na czas kompilacji C i C++.
Wymagania wstępne
- Program Visual Studio 2022 w wersji 17.8 lub nowszej.
- Szczegółowe informacje o kompilacji języka C++ są domyślnie włączone, jeśli zainstalujesz pakiet roboczy Programowanie aplikacji klasycznych w języku C++ przy użyciu instalatora programu Visual Studio:
Zostanie wyświetlona lista zainstalowanych składników. Analiza kompilacji języka C++ jest wyróżniona i jest wybrana, co oznacza, że jest zainstalowana.
Lub programowanie gier z obciążeniem C++:
Zostanie wyświetlona lista zainstalowanych składników. Analiza kompilacji języka C++ jest wyróżniona i jest wybrana, co oznacza, że jest zainstalowana.
Omówienie
Tworzenie szczegółowych informacji, które są teraz zintegrowane z programem Visual Studio, ułatwia optymalizowanie czasów kompilacji — szczególnie w przypadku dużych projektów, takich jak gry triple-A. Gdy duży plik nagłówka jest analizowany, a zwłaszcza gdy jest wielokrotnie analizowany, istnieje wpływ na czas kompilacji.
Funkcja Build Insights udostępnia analizę w widoku Dołączone pliki , co ułatwia diagnozowanie wpływu analizowania #include
plików w projekcie. Wyświetla czas analizowania każdego pliku nagłówka i widoku relacji między plikami nagłówka.
W tym artykule dowiesz się, jak używać wbudowanych plików usługi Build Insights i widoków drzewa dołączania do identyfikowania najdroższych plików nagłówków do analizowania i optymalizowania czasu kompilacji przez utworzenie wstępnie skompilowanego pliku nagłówka.
Ustawianie opcji kompilacji
Przed zebraniem danych usługi Build Insights ustaw opcje kompilacji dla typu kompilacji, którą chcesz zmierzyć. Jeśli na przykład interesuje Cię czas kompilacji debugowania x64, ustaw kompilację debugowania i x64:
Na liście rozwijanej Konfiguracje rozwiązań wybierz pozycję Debuguj.
Na liście rozwijanej Platformy rozwiązań wybierz pozycję x64.
Zostanie wyświetlona lista rozwijana Konfiguracja rozwiązania. Dostępne są opcje debugowania, wydania i programu Configuration Manager. Lista rozwijana Platforma rozwiązania jest ustawiona na x64.
Uruchamianie szczegółowych informacji o kompilacji
W wybranym projekcie i przy użyciu opcji kompilacji debugowania ustawionych w poprzedniej sekcji uruchom polecenie Build Insights, wybierając z menu głównego polecenie Build Build Insights (Kompiluj szczegółowe informacje kompilacji) w polu Build Insights (Kompiluj szczegółowe informacje o kompilacji) w <nazwie>>projektu Rebuild (Kompilowanie> szczegółowych informacji). Możesz również kliknąć prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybrać polecenie Uruchom ponowne kompilowanie szczegółowych informacji>. Wybierz pozycję Skompiluj zamiast kompilacji, aby zmierzyć czas kompilacji dla całego projektu, a nie tylko dla kilku plików, które mogą być teraz zanieczyszczone.
Po zakończeniu kompilacji zostanie otwarty plik dziennika śledzenia zdarzeń (ETL). Jest on zapisywany w folderze wskazywany przez zmienną środowiskową systemu Windows TEMP
. Wygenerowana nazwa jest oparta na czasie zbierania.
Widok dołączonych plików
Plik śledzenia pokazuje czas kompilacji — który w tym przykładzie wynosił 16,404 sekundy. Sesja diagnostyki to ogólny czas potrzebny na uruchomienie sesji usługi Build Insights. Wybierz kartę Dołączone pliki .
Ten widok przedstawia czas spędzony na przetwarzaniu #include
plików.
W kolumnie ścieżka pliku wyróżniono kilka plików z ikoną ognia, ponieważ zajmują ponad 10% czasu kompilacji do przeanalizowania. winrtHeaders.h jest największym z 8,581 sekundy lub 52,3% z 16,404-sekundowego czasu kompilacji.
W kolumnie Ścieżka pliku obok niektórych plików znajduje się ikona uruchamiania wskazująca, że zajmuje 10% lub więcej czasu kompilacji.
Kolumna Time [sec, %] pokazuje, jak długo zajęło skompilowanie każdej funkcji w czasie odpowiedzialności zegara ściany (WCTR). Ta metryka rozkłada czas zegara ściany potrzebny do analizowania plików na podstawie ich użycia wątków równoległych. Jeśli na przykład dwa różne wątki analizują dwa różne pliki jednocześnie w ciągu jednego sekundy, każdy plik WCTR jest rejestrowany jako 0,5 sekundy. Odzwierciedla to proporcjonalny udział każdego pliku w łącznym czasie kompilacji, biorąc pod uwagę zasoby, które są używane podczas równoległego wykonywania. W związku z tym usługa WCTR zapewnia lepszą miarę wpływu, jaki ma każdy plik na ogólny czas kompilacji w środowiskach, w których występuje wiele działań kompilacji jednocześnie.
Kolumna Parse Count (Liczba analiz) pokazuje, ile czasu przeanalizowano plik nagłówka.
Pierwszy plik nagłówka wyróżniony na tej liście to winrtHeaders.h
8,581 sekundy całkowitego czasu kompilacji 16,404 sekundy lub 52,3% czasu kompilacji. Następnym najdroższym elementem jest Windows.UI.Xaml.Interop.h
, a następnie Windows.Xaml.h
.
Aby zobaczyć, który plik zawiera winrtHeaders.h
, kliknij obok niego pagon. Kolumna Liczba analiz może być przydatna, wskazując, ile razy plik nagłówka jest dołączany przez inne pliki. Być może plik nagłówka jest dołączany wiele razy, co może być znakiem, że jest dobrym kandydatem do wstępnie skompilowanego pliku nagłówka lub refaktoryzacji.
Kolumna Jednostka tłumaczenia pokazuje, który plik był przetwarzany podczas przetwarzania dołączonego pliku. W tym przykładzie winrtHeaders.h
został uwzględniony podczas Grapher.cpp
kompilowania:
Przykładowy plik ETL przedstawiający pliki dołączane do przykładowego projektu. W kolumnie ścieżka pliku jest zaznaczona i rozwinięta winrtHeaders.h. Kompilacja trwa 8,219 sekund, co wynosi 50,1% czasu kompilacji. Jego węzeł podrzędny jest Grapher.cpp, który jest również wymieniony jako jednostka tłumaczenia.
Kolumna jednostki tłumaczenia może pomóc w uściślaniu, który plik był kompilowany w przypadkach, gdy plik nagłówka jest dołączany wiele razy i chcesz dowiedzieć się, gdzie dzieje się to najbardziej.
Wiemy, że winrtHeaders.h
analizowanie jest kosztowne, ale możemy dowiedzieć się więcej.
Uwzględnij widok drzewa
W tym widoku węzły podrzędne są plikami dołączonymi do węzła nadrzędnego. Może to pomóc zrozumieć relacje między plikami nagłówka i zidentyfikować możliwości zmniejszenia liczby analiz pliku nagłówka.
Wybierz kartę Uwzględnij drzewo w pliku ETL, aby wyświetlić widok Uwzględnij drzewo:
Pokazuje drzewo dołączania dla projektu. W kolumnie ścieżki pliku każdy plik zawierający inne pliki jest wymieniony wraz z liczbą plików, które zawiera, oraz czas ich analizowania.
W tym widoku kolumna Ścieżka pliku zawiera każdy plik zawierający inne pliki. Liczba uwzględnień zawiera liczbę plików, które zawiera ten plik nagłówka. Czas analizowania tego pliku znajduje się na liście, a po rozwinięciu wyświetla czas analizowania każdego pojedynczego pliku nagłówka, który zawiera ten plik nagłówka.
Wcześniej widzieliśmy, że analizowanie jest czasochłonne winrtHeaders.h
. W polu tekstowym Filter Files (Filtruj pliki ), jeśli wprowadzimy winrtHeaders.h
wartość , możemy filtrować widok tylko do wpisów, które zawierają winrtHeaders.h
nazwę . Kliknięcie cudzysłów obok winrtHeaders.h
pokaże, które pliki zawierają:
Kolumna ścieżka pliku zawiera listę każdego pliku zawierającego inne pliki wraz z liczbą plików, które zawiera, oraz czas, jaki zajęło jej przeanalizowanie. Plik winrtHeaders.h jest zaznaczony i rozwinięty, aby wyświetlić pliki, które zawiera. Windows.UI.Xaml.Interop.h jest jednym z tych plików i jest rozwinięty, aby wyświetlić windows.UI.Xaml.Interop.h, który został rozszerzony, aby wyświetlić pliki nagłówka, które zawiera.
Widzimy, że winrtHeaders.h
zawiera Windows.UI.Xaml.Interop.h
element . Należy pamiętać z widoku Dołączone pliki , że było to również czasochłonne do analizowania. Kliknij pagon obok, aby zobaczyć Windows.UI.Xaml.Interop.h
, że zawiera Windows.UI.Xaml.h
element , który zawiera 21 innych plików nagłówków, z których dwa znajdują się również na gorącej liście.
Po zidentyfikowaniu niektórych z najdroższych plików nagłówków do analizy i zobaczeniu, że winrtHeaders.h
jest to odpowiedzialne za ich wprowadzenie, sugeruje, że możemy użyć prekompilowanego nagłówka, aby przyspieszyć dołączanie winrtHeaders.h
.
Poprawianie czasu kompilacji przy użyciu wstępnie skompilowanych nagłówków
Ponieważ wiemy z widoku Dołączone pliki , który winrtHeaders.h
jest czasochłonny do analizowania, i ponieważ wiemy z widoku Uwzględnij drzewo , który winrtHeaders.h
zawiera kilka innych plików nagłówków, które są czasochłonne do analizowania, tworzymy prekompilowany plik nagłówka (PCH), aby przyspieszyć to przez tylko analizowanie ich raz w PCH.
Dodamy element pch.h
, winrtHeaders.h
który będzie wyglądać następująco:
#ifndef CALC_PCH
#define CALC_PCH
#include <winrtHeaders.h>
#endif // CALC_PCH
Pliki PCH należy skompilować przed ich zastosowaniem, dlatego do projektu dodamy plik o dowolnej nazwie pch.cpp
, który zawiera pch.h
element . Zawiera jeden wiersz:
#include "pch.h"
Następnie ustawiliśmy projekt tak, aby używał PCH. Odbywa się to we właściwościach projektu za pomocą prekompilowanych nagłówków języka C/C++>i ustawiania prekompilowanego nagłówka na wartość Użyj (/Yu) i prekompilowanego pliku nagłówka na wartość pch.h.
Prekompilowany nagłówek jest ustawiony na: Użyj (/Yu). Prekompilowany plik nagłówka jest ustawiony na wartość pch.h.
Aby użyć PCH, dołączymy go jako pierwszy wiersz w plikach źródłowych, które używają polecenia winrtHeaders.h
. Musi ona znajdować się przed innymi plikami dołączania. Dla uproszczenia można też zmodyfikować właściwości projektu tak, aby zawierały pch.h
na początku każdego pliku w rozwiązaniu, ustawiając właściwość projektu: C/C++>Advanced>Forced Include File na : pch.h
Plik dołączania wymuszonego jest ustawiony na wartość pch.h.
Ponieważ PCH zawiera winrtHeaders.h
element , możemy usunąć winrtHeaders.h
ze wszystkich plików, które obecnie go zawierają. Nie jest to ściśle konieczne, ponieważ kompilator zdaje sobie sprawę, że winrtHeaders.h
jest już uwzględniony i nie analizuje go ponownie. Niektórzy deweloperzy wolą zachować #include
w pliku źródłowym czytelność lub w przypadku, gdy PCH prawdopodobnie zostanie refaktoryzowany i może już nie zawierać tego pliku nagłówka.
Testowanie zmian
Najpierw wyczyścimy projekt, aby upewnić się, że porównujemy kompilowanie tych samych plików co poprzednio. Aby wyczyścić tylko jeden projekt, kliknij prawym przyciskiem myszy projekt w Eksplorator rozwiązań i wybierz polecenie Project only Clean only prj name (Tylko>wyczyść tylko <nazwę> prj).
Ponieważ ten projekt używa teraz wstępnie skompilowanego nagłówka (PCH), nie chcemy mierzyć czasu spędzonego na tworzeniu PCH, ponieważ dzieje się to tylko raz. Robimy to, ładując pch.cpp
plik i wybierając Ctrl+F7 , aby skompilować tylko ten plik. Możemy również skompilować ten plik, klikając prawym przyciskiem pch.cpp
myszy Eksplorator rozwiązań i wybierając polecenie Compile
.
Teraz ponownie uruchomimy usługę Build Insights w Eksplorator rozwiązań, klikając prawym przyciskiem myszy projekt i wybierając pozycję Project Only Run Build Insights on Build Insights on Build (Uruchom tylko>szczegółowe informacje kompilacji w programie Project) w kompilacji. Możesz również kliknąć prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybrać polecenie Uruchom kompilację szczegółowych informacji>. Nie chcemy ponownie kompilować tym razem, ponieważ spowoduje to odbudowę PCH, której nie chcemy zmierzyć. Wcześniej oczyściliśmy projekt, co oznacza, że normalna kompilacja kompiluje wszystkie pliki projektu, które chcemy zmierzyć.
Gdy pojawią się pliki ETL, zobaczymy, że czas kompilacji spadł z 16,404 sekundy do 6,615 sekund. Umieść winrtHeaders.h
w polu filtru i nic się nie pojawia. Wynika to z faktu, że czas spędzony na analizowaniu jest teraz niewielki, ponieważ jest on ściągany przez prekompilowany nagłówek.
W tym przykładzie użyto wstępnie skompilowanych nagłówków, ponieważ są one typowym rozwiązaniem przed językiem C++20. Jednak począwszy od języka C++20 istnieją inne, szybsze, mniej kruche, sposoby dołączania plików nagłówków — takich jak jednostki nagłówka i moduły. Aby uzyskać więcej informacji, zobacz Porównanie jednostek nagłówka, modułów i prekompilowanych nagłówków.
Nawigowanie między widokami
Istnieją pewne funkcje nawigacji zarówno dla uwzględnionych plików, jak i widoków drzewa dołączania:
- Kliknij dwukrotnie plik (lub naciśnij Enter) w uwzględnionych plikach lub drzewie dołączania, aby otworzyć kod źródłowy dla tego pliku.
- Kliknij prawym przyciskiem myszy plik nagłówkowy, aby znaleźć ten plik w innym widoku. Na przykład w widoku Uwzględnij plikkliknij prawym przyciskiem myszy
winrtHeaders.h
i wybierz polecenie Znajdź w drzewie dołączania, aby wyświetlić go w widoku Uwzględnij drzewo.
Możesz też kliknąć prawym przyciskiem myszy plik w widoku Uwzględnij drzewo , aby przejść do niego w widoku Dołączone pliki .
Wskazówki
- Możesz zapisać plik>jako plik ETL w bardziej trwałej lokalizacji, aby zachować rekord czasu kompilacji. Następnie możesz porównać ją z przyszłymi kompilacjami, aby sprawdzić, czy zmiany skracają czas kompilacji.
- Jeśli przypadkowo zamkniesz okno Build Insights, otwórz je ponownie, wyszukując
<dateandtime>.etl
plik w folderze tymczasowym. ZmiennaTEMP
środowiskowa systemu Windows zawiera ścieżkę folderu plików tymczasowych. - Aby zapoznać się z danymi build insights w systemie Windows Analizator wydajności (WPA), kliknij przycisk Otwórz w usłudze WPA w prawym dolnym rogu okna ETL.
- Przeciągnij kolumny, aby zmienić kolejność kolumn. Na przykład możesz wolisz przenieść kolumnę Time ( Czas ) jako pierwszą kolumnę. Możesz ukryć kolumny, klikając prawym przyciskiem myszy nagłówek kolumny i usuwając zaznaczenie kolumn, których nie chcesz zobaczyć.
- Widoki Dołączone pliki i Uwzględnij drzewa zawierają pole filtru, aby znaleźć interesujący Cię plik nagłówkowy. Wykonuje częściowe dopasowania w podanej nazwie.
- Czasami czas analizy zgłoszony dla pliku nagłówka różni się w zależności od tego, który plik zawiera. Może to być spowodowane międzyoperacyjnością różnych
#define
elementów, które mają wpływ na to, które części nagłówka są rozwinięte, buforowanie plików i inne czynniki systemowe. - Jeśli zapomnisz, co chcesz wyświetlić w widoku Dołączone pliki lub Dołącz drzewo , umieść kursor na karcie, aby wyświetlić etykietkę narzędzia opisjącą widok. Jeśli na przykład zatrzymasz wskaźnik myszy na karcie Uwzględnij drzewo , etykietka narzędzia będzie zawierać następujące informacje: "Wyświetl, które zawierają statystyki dla każdego pliku, w którym węzły podrzędne są plikami dołączonymi przez węzeł nadrzędny".
- Mogą wystąpić przypadki (na przykład
Windows.h
), w których zagregowany czas trwania pliku nagłówka jest dłuższy niż czas trwania całej kompilacji. Dzieje się tak, że nagłówki są analizowane w wielu wątkach w tym samym czasie. Jeśli dwa wątki jednocześnie spędzają jedną sekundę podczas analizowania pliku nagłówka, jest to 2 sekundy czasu kompilacji, mimo że minęła tylko jedna sekunda czasu zegara ściany. Aby uzyskać więcej informacji, zobacz czas odpowiedzialności zegara ściany (WCTR).
Rozwiązywanie problemów
- Jeśli okno Build Insights nie zostanie wyświetlone, wykonaj ponowną kompilację zamiast kompilacji. Okno Build Insights (Szczegółowe informacje o kompilacji) nie jest wyświetlane, jeśli faktycznie nic nie zostanie skompiluje; może to być przypadek, jeśli żadne pliki nie uległy zmianie od ostatniej kompilacji.
- Jeśli interesujący Cię plik nagłówkowy nie jest wyświetlany w widokach Dołączone pliki lub Uwzględnij drzewo, nie został on skompilowany lub jego czas kompilacji nie jest wystarczająco znaczący, aby zostać wyświetlony.
Zobacz też
Porady i wskazówki dotyczące tworzenia szczegółowych informacji
Porównanie jednostek nagłówka, modułów i wstępnie skompilowanych nagłówków
Tworzenie szczegółowych informacji w programie Visual Studio wideo — Pure Virtual C++ 2023
Szybsze kompilacje języka C++, uproszczone: nowa metryka na czas
Rozwiązywanie problemów z tworzeniem funkcji w czasie kompilacji
vcperf i Windows Analizator wydajności