Udostępnij za pośrednictwem


Samouczek: rozwiązywanie problemów z wpływem pliku nagłówka na czas kompilacji

Użyj opcji Kompiluj Szczegółowe informacje dołączonych plików i uwzględnij widoki 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 kompilacji języka C++ jest domyślnie włączona, jeśli zainstalujesz pakiet roboczy Programowanie aplikacji klasycznych w języku C++ przy użyciu instalatora programu Visual Studio:

Zrzut ekranu przedstawiający Instalator programu Visual Studio z wybranym obciążeniem Programowanie aplikacji klasycznych w języku C++.

Zostanie wyświetlona lista zainstalowanych składników. Szczegółowe informacje kompilacji języka C++ jest wyróżniona i jest zaznaczona, co oznacza, że jest zainstalowany.

Lub programowanie gier z obciążeniem C++:

Zrzut ekranu przedstawiający Instalator programu Visual Studio z wybranym obciążeniem Programowanie gier w języku C++.

Zostanie wyświetlona lista zainstalowanych składników. Szczegółowe informacje kompilacji języka C++ jest wyróżniona i jest zaznaczona, co oznacza, że jest zainstalowany.

Omówienie

Tworzenie Szczegółowe informacje, 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.

Kompilacja Szczegółowe informacje 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ć widoków kompilacji Szczegółowe informacje dołączonych plików i uwzględnić drzewa, aby zidentyfikować najdroższe pliki nagłówkowe do przeanalizowania i jak zoptymalizować czas kompilacji przez utworzenie wstępnie skompilowanego pliku nagłówka.

Ustawianie opcji kompilacji

Przed zebraniem danych kompilacji Szczegółowe informacje 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.

    Zrzut ekranu przedstawiający listy rozwijane Konfiguracja rozwiązania.

    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ółowe informacje kompilacji

W wybranym projekcie i przy użyciu opcji kompilacji Debuguj ustawionej w poprzedniej sekcji uruchom polecenie Kompiluj Szczegółowe informacje, wybierając z menu głównego polecenie Kompiluj>kompilację Uruchom kompilację Szczegółowe informacje przy kompilowaniu zaznaczenia.> Możesz również kliknąć prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybrać polecenie Uruchom kompilację Szczegółowe informacje> Rebuild. 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.

Zrzut ekranu przedstawiający menu główne z wybraną Szczegółowe informacje Uruchom kompilację w obszarze Ponowne kompilowanie zaznaczenia>.

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 kompilacji Szczegółowe informacje. Wybierz kartę Dołączone pliki .

Ten widok przedstawia czas spędzony na przetwarzaniu #include plików.

Zrzut ekranu przedstawiający widok dołączonych 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:

Zrzut ekranu przedstawiający widok Dołączone pliki.

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:

Zrzut ekranu przedstawiający 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.hwartość , 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ą:

Zrzut ekranu przedstawiający rozwinięty widok Uwzględnij drzewo.

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.helement . 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.helement , 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.hktó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.helement . 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.

Zrzut ekranu przedstawiający okno dialogowe właściwości projektu z otwartymi ustawieniami Prekompilowane nagłówki.

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

Zrzut ekranu przedstawiający okno dialogowe właściwości projektu z otwartymi ustawieniami zaawansowanymi.

Plik dołączania wymuszonego jest ustawiony na wartość pch.h.

Ponieważ PCH zawiera winrtHeaders.helement , 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 klawisze 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 uruchomimy ponownie Szczegółowe informacje kompilacji w Eksplorator rozwiązań, klikając projekt prawym przyciskiem myszy i wybierając pozycję Project Only Run Build Szczegółowe informacje on Build (Kompilacja tylko>w programie Project Run Build). Możesz również kliknąć prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybrać polecenie Uruchom kompilację Szczegółowe informacje> Build. 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.

Zrzut ekranu przedstawiający okienko Uwzględnij drzewo w pliku śledzenia. WinrtHeaders nie jest już wymieniony.

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.

Istnieją pewne funkcje nawigacji zarówno dla uwzględnionych plików, jak i widoków drzewa dołączania:

  • Kliknij dwukrotnie plik (lub naciśnij klawisz Enter) w uwzględnionych plikach lub drzewiedołą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.

Zrzut ekranu przedstawiający kliknięcie prawym przyciskiem myszy pliku w widoku Dołączone pliki. Opcja menu Pokaż w widoku drzewa dołącz jest wyróżniona.

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 Kompilacja Szczegółowe informacje, otwórz go ponownie, wyszukując <dateandtime>.etl plik w folderze tymczasowym. Zmienna TEMP środowiskowa systemu Windows zawiera ścieżkę folderu plików tymczasowych.
  • Aby zagłębić się w dane kompilacji Szczegółowe informacje przy użyciu usługi Windows Analizator wydajności (WPA), kliknij przycisk Otwórz w programie 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 #defineelementó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 nie zostanie wyświetlone okno Kompilowanie Szczegółowe informacje, wykonaj ponowną kompilację zamiast kompilacji. Okno Kompilowanie Szczegółowe informacje nie jest wyświetlane, jeśli faktycznie nic nie zostanie skompiluje, co może mieć miejsce, 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ż

Porównanie jednostek nagłówka, modułów i wstępnie skompilowanych nagłówków
Kompilowanie Szczegółowe informacje w programie Visual Studio — Pure Virtual C++ 2023
Szybsze kompilacje języka C++, uproszczone: nowa metryka na czas
Samouczek: rozwiązywanie problemów z tworzeniem w czasie kompilacji funkcji
Samouczek: vcperf i Windows Analizator wydajności