Sdílet prostřednictvím


Kurz: Řešení potíží s dopadem hlavičkového souboru na čas sestavení

Pomocí zahrnutých #include souborů Build Insights a zobrazení stromové struktury můžete řešit potíže s dopadem souborů na časy sestavení C a C++.

Požadavky

  • Visual Studio 2022 17.8 nebo novější
  • Nástroj C++ Build Insights je ve výchozím nastavení povolený, pokud pomocí instalačního programu sady Visual Studio nainstalujete buď vývoj desktopových aplikací pomocí sady C++:

Snímek obrazovky s Instalační program pro Visual Studio s vybranou úlohou Desktop development with C++ (Vývoj desktopových aplikací s vybranou úlohou C++).

Zobrazí se seznam nainstalovaných komponent. Zvýrazní se přehledy sestavení C++ a vybere se, což znamená, že je nainstalované.

Nebo vývoj her pomocí úlohy C++:

Snímek obrazovky Instalační program pro Visual Studio s vybranou úlohou Vývoj her s vybranou úlohou C++.

Zobrazí se seznam nainstalovaných komponent. Zvýrazní se přehledy sestavení C++ a vybere se, což znamená, že je nainstalované.

Přehled

Funkce Build Insights, která je teď integrovaná do sady Visual Studio, vám pomůže optimalizovat časy sestavení – zejména pro velké projekty, jako jsou hry typu triple-A. Když se parsuje velký soubor záhlaví, a to zejména v případě, že se soubor opakovaně analyzuje, bude mít vliv na čas sestavení.

Build Insights poskytuje analýzy v zobrazení Zahrnuté soubory , které pomáhají diagnostikovat dopad analýzy #include souborů ve vašem projektu. Zobrazuje dobu potřebnou k analýze jednotlivých souborů hlaviček a zobrazení relací mezi soubory hlaviček.

V tomto článku se dozvíte, jak používat zahrnuté soubory Build Insights a Zahrnout stromová zobrazení k identifikaci nejdražších souborů hlaviček k analýze a optimalizaci doby sestavení vytvořením předkompilovaného souboru hlaviček.

Nastavení možností sestavení

Před shromažďováním dat Build Insights nastavte možnosti sestavení pro typ sestavení, který chcete měřit. Pokud se například zajímáte o čas sestavení pro ladění x64, nastavte sestavení pro ladění a x64:

  • V rozevíracím seznamu Konfigurace řešení zvolte Ladit.

  • V rozevíracím seznamu Platformy řešení zvolte x64.

    Snímek obrazovky s rozevíracími seznamy Konfigurace řešení

    Zobrazí se rozevírací seznam Konfigurace řešení. Má možnosti pro ladění, vydávání a configuration manager. Rozevírací seznam Řešení platformy je nastavený na x64.

Spuštění buildových přehledů

V projektu podle vašeho výběru a použití možností sestavení ladění nastavené v předchozí části spusťte Build Insights výběrem z hlavní nabídky Sestavení>Spustit přehledy sestavení při opětovném sestavení výběru.> Můžete také kliknout pravým tlačítkem myši na projekt v Průzkumníku řešení a zvolit Spustit opětovné sestavení Build Insights.> Místo sestavení zvolte Znovu sestavit, abyste změřili čas sestavení pro celý projekt, a ne jenom pro několik souborů, které teď můžou být zašpiněné.

Snímek obrazovky hlavní nabídky s vybranou možností Spustit přehledy sestavení při opětovném sestavení výběru >

Po dokončení sestavení se otevře soubor ETL (Event Trace Log). Uloží se do složky, na kterou odkazuje proměnná prostředí Windows TEMP . Vygenerovaný název vychází z času shromažďování.

Zobrazení Zahrnuté soubory

Trasovací soubor ukazuje čas sestavení, který v tomto příkladu byl 16,404 sekund. Diagnostická relace je celková doba potřebná ke spuštění relace Build Insights. Zvolte kartu Zahrnuté soubory.

Toto zobrazení ukazuje čas strávený zpracováním #include souborů.

Snímek obrazovky se zobrazením zahrnutých souborů

Ve sloupci cesta k souboru je zvýrazněno několik souborů s ikonou aktivace, protože parsování trvá více než 10 % času sestavení. winrtHeaders.h je největší v 8,581 sekundách nebo 52,3 % z 16,404 sekundy sestavení.

Ve sloupci Cesta k souboru mají některé soubory vedle nich ikonu aktivace, která označuje, že zabírají 10 % nebo více času sestavení.

Sloupec Time [sec, %] ukazuje, jak dlouho trvalo kompilaci jednotlivých funkcí v době odpovědnosti za nástěnné hodiny (WCTR). Tato metrika distribuuje hodinovou dobu, která trvá parsování souborů na základě jejich použití paralelních vláken. Pokud například dvě různá vlákna parsují dva různé soubory současně během jedné sekundy, zaznamená se WCTR každého souboru jako 0,5 sekundy. To odráží proporcionální podíl celkového času kompilace jednotlivých souborů s ohledem na prostředky spotřebované během paralelního provádění. WCTR tedy poskytuje lepší míru dopadu každého souboru na celkovou dobu sestavení v prostředích, kde současně probíhá více aktivit kompilace.

Sloupec Parse Count (Počet parse) zobrazuje, kolikrát se soubor záhlaví parsoval.

První soubor záhlaví zvýrazněný v tomto seznamu je winrtHeaders.h 8,581 sekund celkového času sestavení 16,404 sekundy nebo 52,3 % času sestavení. Další nejnákladnější je Windows.UI.Xaml.Interop.ha pak Windows.Xaml.h.

Pokud chcete zjistit, který soubor obsahuje winrtHeaders.h, klikněte na dvojitou šipku vedle něj. Sloupec Parse Count může být užitečný tím, že ukazuje, kolikrát je soubor záhlaví součástí jiných souborů. Soubor hlaviček je možná součástí vícekrát, což může být znaménkem, že je vhodným kandidátem na předkompilovaný soubor hlaviček nebo refaktoring.

Sloupec Jednotka překladu ukazuje, který soubor byl zpracován při zpracování zahrnutého souboru. V tomto příkladu winrtHeaders.h byla zahrnuta během Grapher.cpp kompilace:

Snímek obrazovky se zobrazením Zahrnuté soubory

Příklad souboru ETL zobrazující soubory zahrnutí pro ukázkový projekt. Ve sloupci cesta k souboru je vybrána a rozbalována winrtHeaders.h. Sestavení trvá 8,219 sekund, což je 50,1 % času sestavení. Jeho podřízený uzel je Grapher.cpp, který je také uveden jako jednotka překladu."

Sloupec jednotky překladu může pomoct nejednoznačit, který soubor byl zkompilován v případech, kdy je hlavičkový soubor často zahrnut a chcete zjistit, kde k tomu dochází nejvíce.

Víme, že winrtHeaders.h je analýza nákladná, ale můžeme se dozvědět více.

Zahrnout stromové zobrazení

V tomto zobrazení jsou podřízené uzly soubory zahrnuté nadřazeným uzlem. To vám může pomoct pochopit vztahy mezi soubory hlaviček a identifikovat příležitosti ke snížení počtu parsovaných souborů hlaviček.

Výběrem karty Zahrnout strom v souboru ETL zobrazte zobrazení Zahrnout strom:

Snímek obrazovky se zobrazením Zahrnout strom

Zobrazuje strom zahrnutí projektu. Ve sloupci cesta k souboru je uveden každý soubor, který obsahuje další soubory, spolu s počtem souborů, které obsahuje, a čas, jak ho analyzovat.

V tomto zobrazení se ve sloupci Cesta k souboru zobrazí každý soubor, který obsahuje další soubory. Počet zahrnutí uvádí, kolik souborů obsahuje tento soubor záhlaví. Čas parsování tohoto souboru je uvedený a při rozbalení uvádí čas parsování každého jednotlivého hlavičkového souboru, který tento soubor záhlaví obsahuje.

Dříve jsme viděli, že analýza winrtHeaders.h je časově náročná. Pokud v textovém poli Filtrovat soubory zadáme winrtHeaders.h, můžeme zobrazení filtrovat pouze na položky, které obsahují winrtHeaders.h v názvu. Kliknutím na dvojitou šipku vedle zobrazíte winrtHeaders.h , které soubory obsahuje:

Snímek obrazovky s rozbaleným zobrazením Zahrnout strom

Sloupec cesty k souboru obsahuje každý soubor, který obsahuje jiné soubory, spolu s počtem souborů, které obsahuje, a čas, který trvalo jeho parsování. WinrtHeaders.h je vybrán a rozbalený, aby se zobrazily soubory, které obsahuje. Windows.UI.Xaml.Interop.h je jedním z těchto souborů a rozbalí se tak, aby zobrazoval soubory hlaviček, které obsahuje, se zobrazují v souboru Windows.UI.Xaml.Interop.h.

Vidíme, že winrtHeaders.h zahrnuje Windows.UI.Xaml.Interop.h. Vzpomeňte si ze zobrazení Zahrnuté soubory , které bylo také časově náročné na analýzu. Kliknutím na dvojitou šipku vedle Windows.UI.Xaml.Interop.h zobrazíte, že obsahuje Windows.UI.Xaml.h21 dalších souborů záhlaví, z nichž dva jsou také v seznamu hot.

Po zjištění některých z nejdražších souborů hlaviček k analýze a zjištění, že winrtHeaders.h je zodpovědný za jejich přenesení, naznačuje, že můžeme použít předkompilovanou hlavičku, která zajistí rychlejší zahrnutí winrtHeaders.h .

Vylepšení času sestavení pomocí předkompilovaných hlaviček

Vzhledem k tomu, že víme ze zobrazení Zahrnuté soubory , které winrtHeaders.h je časově náročné k analýze, a protože víme ze stromového zobrazení Zahrnout, které winrtHeaders.h obsahuje několik dalších souborů hlaviček, které jsou časově náročné k analýze, vytvoříme předkompilovaný soubor hlaviček (PCH), abychom to urychlili tak, že je parsujeme pouze jednou do PCH.

Přidáme pch.h k zahrnutí winrtHeaders.h, která by vypadala takto:

#ifndef CALC_PCH
#define CALC_PCH

#include <winrtHeaders.h>

#endif // CALC_PCH

Soubory PCH musí být zkompilovány dříve, než je lze použít, takže do projektu přidáme soubor, který je libovolně pojmenovaný pch.cpp, který zahrnuje pch.h. Obsahuje jeden řádek:

#include "pch.h"

Pak nastavíme projekt tak, aby používal PCH. To se provádí ve vlastnostech projektu prostřednictvím předkompilovaných hlaviček C/C++> a nastavení předkompilované hlavičky pro použití (/Yu) a předkompilovaného hlavičkového souboru na pch.h.

Snímek obrazovky s dialogovým oknem vlastností projektu s otevřeným nastavením Předkompilované hlavičky

Předkompilované záhlaví je nastavené na: Použít (/Yu). Předkompilovaný hlavičkový soubor je nastaven na pch.h.

Abychom mohli použít PCH, zahrneme ho jako první řádek do zdrojových souborů, které používají winrtHeaders.h. Musí předcházet jiným souborům zahrnutí. Nebo pro zjednodušení bychom mohli upravit vlastnosti projektu tak, aby zahrnovaly pch.h na začátku každého souboru v řešení nastavením vlastnosti projektu: C/C++>Advanced>Forced Include File na:pch.h

Snímek obrazovky s dialogovým oknem vlastností projektu s otevřeným rozšířeným nastavením

Vynucený soubor zahrnutí je nastaven na pch.h.

Vzhledem k tomu, že PCH obsahuje winrtHeaders.h, můžeme odebrat winrtHeaders.h ze všech souborů, které ho aktuálně obsahují. Není to nezbytně nutné, protože kompilátor zjistí, že winrtHeaders.h už je zahrnutý a znovu ho parsuje. Někteří vývojáři dávají přednost zachování #include zdrojového souboru pro přehlednost, nebo v případě, že PCH bude pravděpodobně refaktorován a nemusí už tento soubor hlaviček obsahovat.

Otestování změn

Nejprve projekt vyčistíme, abychom se ujistili, že porovnáváme sestavování stejných souborů jako předtím. Chcete-li vyčistit pouze jeden projekt, klikněte pravým tlačítkem myši na projekt v Průzkumník řešení a zvolte pouze název projektu Vyčistit pouze <>prj.>

Vzhledem k tomu, že tento projekt teď používá předkompilovanou hlavičku (PCH), nechceme měřit čas strávený sestavováním PCH, protože k tomu dochází jen jednou. Provedeme to načtením pch.cpp souboru a zvolením kombinace kláves Ctrl+F7 sestavte jenom tento soubor. Tento soubor můžeme také zkompilovat tak, že kliknete pravým tlačítkem na pch.cpp Průzkumník řešení a zvolíme Compile.

Teď znovu spustíme Build Insights v Průzkumník řešení tak, že kliknete pravým tlačítkem na projekt a zvolíme Project>Only Run Build Insights on Build Insights on Build Insights. Můžete také kliknout pravým tlačítkem na projekt v Průzkumníku řešení a zvolit Spustit build Build Insights>. Tentokrát nechceme znovu sestavit , protože se tím znovu sestaví PCH, což nechceme měřit. Projekt jsme vyčistili dříve, což znamená, že normální sestavení zkompiluje všechny soubory projektu, které chceme měřit.

Když se zobrazí soubory ETL, vidíme, že čas sestavení šel z 16,404 sekund na 6,615 sekund. Vložte winrtHeaders.h do pole filtru a nic se nezobrazí. Důvodem je to, že čas strávený analýzou je teď zanedbatelný, protože se načítá předkompilovanou hlavičkou.

Snímek obrazovky s podoknem Zahrnout strom v trasovacím souboru WinrtHeaders už tu není uvedený.

Tento příklad používá předkompilované hlavičky, protože se jedná o běžné řešení před C++20. Počínaje jazykem C++20 však existují další, rychlejší, méně křehké způsoby, jak zahrnout soubory hlaviček, jako jsou jednotky hlaviček a moduly. Další informace najdete v tématu Porovnání jednotek hlaviček, modulů a předkompilovaných hlaviček.

K dispozici jsou některé navigační funkce pro zahrnuté soubory i zobrazení Zahrnout strom :

  • Poklikejte na soubor (nebo stiskněte Enter) v zahrnutých souborech nebo ve stromu Zahrnout a otevřete zdrojový kód pro tento soubor.
  • Kliknutím pravým tlačítkem myši na soubor záhlaví najděte tento soubor v druhém zobrazení. Například v zobrazení Zahrnutý souborklikněte pravým tlačítkem myši winrtHeaders.h a zvolte Najít v zahrnout strom , aby se zobrazil v zobrazení Zahrnout strom .

Snímek obrazovky s kliknutím pravým tlačítkem myši na soubor v zobrazení Zahrnuté soubory Možnost nabídky Zobrazit v zahrnout stromové zobrazení je zvýrazněná.

Nebo můžete kliknout pravým tlačítkem myši na soubor v zobrazení Zahrnout strom a přejít na něj v zobrazení Zahrnuté soubory .

Tipy

  • Soubor Uložit jako soubor ETL můžete >uložit do trvalejšího umístění, abyste si zachovali záznam o čase sestavení. Pak ho můžete porovnat s budoucími buildy a zjistit, jestli se vaše změny zlepšují čas sestavení.
  • Pokud neúmyslně zavřete okno Build Insights, znovu ho otevřete vyhledáním <dateandtime>.etl souboru v dočasné složce. TEMP Proměnná prostředí Windows poskytuje cestu ke složce dočasných souborů.
  • Chcete-li se podívat na data Build Insights s Windows Analyzátor výkonu (WPA), klikněte v pravém dolním rohu okna ETL na tlačítko Otevřít v WPA.
  • Přetažením sloupců můžete změnit pořadí sloupců. Můžete například raději přesunout sloupec Čas na první sloupec. Sloupce můžete skrýt tak, že kliknete pravým tlačítkem myši na záhlaví sloupce a zrušíte výběr sloupců, které nechcete zobrazit.
  • Zobrazení Zahrnuté soubory a Zahrnout strom poskytují pole filtru pro vyhledání souboru záhlaví, který vás zajímá. Provede částečné shody u zadaného názvu.
  • V závislosti na tom, který soubor obsahuje, se někdy liší čas analýzy souboru záhlaví. Může to být způsobeno přehráním různých #defines, které ovlivňují, které části hlavičky jsou rozbalené, ukládání souborů do mezipaměti a další systémové faktory.
  • Pokud zapomenete, co se vám v zobrazení Zahrnuté soubory nebo Zahrnout strom pokouší zobrazit, najeďte myší na kartu a podívejte se na popis, který toto zobrazení popisuje. Pokud například najedete myší na kartu Zahrnout strom , zobrazí se popis: "View that shows include statistics for every file where the child node are the files include the files include the parent node" (Zobrazení, které zobrazuje statistiku zahrnutí pro každý soubor, ve kterém jsou podřízené uzly soubory zahrnuté nadřazeným uzlem).
  • Můžou se zobrazit případy (například Windows.h), kdy agregovaná doba trvání všech časů pro soubor hlaviček je delší než doba trvání celého sestavení. Děje se to, že se hlavičky analyzují na více vláknech současně. Pokud dvě vlákna současně tráví jednou sekundou parsováním souboru záhlaví, je to 2 sekundy času sestavení, i když uplynula jen jedna sekunda hodinového času. Další informace najdete v tématu čas odpovědnosti za nástěnné hodiny (WCTR).

Řešení problému

  • Pokud se okno Build Insights nezobrazí, místo sestavení proveďte opětovné sestavení. Okno Build Insights se nezobrazí, pokud se ve skutečnosti nic nevytvorí; což může být případ, kdy se od posledního sestavení nezměnily žádné soubory.
  • Pokud se soubor záhlaví, který vás zajímá, nezobrazuje v zobrazení Zahrnuté soubory nebo Zahrnout strom , buď se nevytvořil, nebo jeho čas sestavení nestačí k uvedení.

Viz také

Porovnání jednotek záhlaví, modulů a předkompilovaných hlaviček
Build Insights in Visual Studio video – Pure Virtual C++ 2023
Rychlejší sestavení jazyka C++, zjednodušená: nová metrika pro čas
Kurz: Řešení potíží s inlineováním funkcí v době sestavení
Kurz: vcperf a Windows Analyzátor výkonu