Sada SDK pro C++ Build Insights
Sada C++ Build Insights SDK je kompatibilní se sadou Visual Studio 2017 a novějšími verzemi. Pokud chcete zobrazit dokumentaci k těmto verzím, nastavte ovládací prvek selektoru verzí sady Visual Studio pro tento článek na Visual Studio 2017 nebo novější. Nachází se v horní části obsahu na této stránce.
Sada C++ Build Insights SDK je kolekce rozhraní API, která umožňují vytvářet přizpůsobené nástroje na platformě C++ Build Insights. Tato stránka obsahuje základní přehled, který vám pomůže začít.
Získání sady SDK
Sadu SDK C++ Build Insights si můžete stáhnout jako balíček NuGet pomocí následujícího postupu:
- V sadě Visual Studio 2017 a novějších vytvořte nový projekt C++.
- V podokně Průzkumník řešení klikněte pravým tlačítkem na projekt.
- V místní nabídce vyberte Spravovat balíčky NuGet.
- V pravém horním rohu vyberte zdroj balíčku nuget.org .
- Vyhledejte nejnovější verzi balíčku Microsoft.Cpp.BuildInsights.
- Zvolte Nainstalovat.
- Přijměte licenci.
Přečtěte si informace o obecných konceptech kolem sady SDK. Můžete také získat přístup k oficiálnímu úložišti GitHub s ukázkami buildů C++, abyste viděli příklady skutečných aplikací C++, které používají sadu SDK.
Shromažďování trasování
K analýze událostí přicházejících ze sady nástrojů MSVC je potřeba nejprve shromáždit trasování pomocí sady SDK pro sestavení jazyka C++. Sada SDK používá trasování událostí pro Windows (ETW) jako základní technologii trasování. Shromažďování trasování lze provést dvěma způsoby:
Metoda 1: Použití vcperf v sadě Visual Studio 2019 a novější
Otevřete příkazový řádek nativních nástrojů x64 se zvýšenými oprávněními pro VS 2019.
Spusťte následující příkaz:
vcperf /start MySessionName
.Sestavte svůj projekt.
Spusťte následující příkaz:
vcperf /stopnoanalyze MySessionName outputTraceFile.etl
.Důležité
/stopnoanalyze
Při zastavování trasování pomocí nástroje vcperf použijte příkaz. Sadu SDK C++ Build Insights nemůžete použít k analýze trasování zastavených pravidelným/stop
příkazem.
Metoda 2: programově
K programovému spuštění a zastavení trasování použijte některou z těchto funkcí trasování sady C++ Build Insights SDK. Program, který spouští tato volání funkcí, musí mít oprávnění správce. Pouze funkce pro spuštění a zastavení trasování vyžadují oprávnění správce. Všechny ostatní funkce v sadě C++ Build Insights SDK je možné spouštět bez nich.
Funkce sady SDK související s kolekcí trasování
Funkce | Rozhraní API C++ | C API |
---|---|---|
Spuštění trasování | StartTracingSession | StartTracingSessionA StartTracingSessionW |
Zastavení trasování | StopTracingSession | StopTracingSessionA StopTracingSessionW |
Zastavení trasování a okamžitá analýza výsledku |
StopAndAnalyzeTracingSession | StopAndAnalyzeTracingSessionA StopAndAnalyzeTracingSession |
Zastavení trasování a okamžité opětovné zalogování výsledku |
StopAndRelogTracingSession | StopAndRelogTracingSessionA StopAndRelogTracingSessionW |
V následujících částech se dozvíte, jak nakonfigurovat analýzu nebo relaci relogování. Vyžaduje se pro kombinované funkce, jako je StopAndAnalyzeTracingSession.
Využívání trasování
Jakmile budete mít trasování Trasování událostí pro Windows, použijte k rozbalení sadu SDK C++ Build Insights. Sada SDK poskytuje události ve formátu, který umožňuje rychle vyvíjet nástroje. Bez použití sady SDK nedoporučujeme využívat nezpracované trasování trasování Trasování událostí pro Windows. Formát události používaný msVC je nezdokumentovaný, optimalizovaný tak, aby se škáloval na obrovské buildy, a těžko dávat smysl. Kromě toho je rozhraní API sady SDK pro Build Insights jazyka C++ stabilní, zatímco nezpracovaný formát trasování trasování událostí pro Windows se může bez předchozího upozornění změnit.
Typy a funkce sady SDK související se spotřebou trasování
Funkce | Rozhraní API C++ | C API | Notes |
---|---|---|---|
Nastavení zpětných volání událostí | IAnalyzer IRelogger |
ANALYSIS_CALLBACKS RELOG_CALLBACKS |
Sada C++ Build Insights SDK poskytuje události prostřednictvím funkcí zpětného volání. V jazyce C++ implementujte funkce zpětného volání vytvořením analyzátoru nebo relogger třídy, která dědí rozhraní IAnalyzer nebo IRelogger. V jazyce C implementujte zpětná volání v globálních funkcích a poskytněte na ně ukazatele ve struktuře ANALYSIS_CALLBACKS nebo RELOG_CALLBACKS. |
Vytváření skupin | MakeStaticAnalyzerGroup MakeStaticReloggerGroup MakeDynamicAnalyzerGroup MakeDynamicReloggerGroup |
Rozhraní API jazyka C++ poskytuje pomocné funkce a typy pro seskupení více analyzátorů a relogger objektů dohromady. Skupiny představují elegantní způsob rozdělení komplexní analýzy do jednodušších kroků. Vcperf je uspořádaný tímto způsobem. | |
Analýza nebo relogování | Analýza Relog |
Analýza A AnalyzeW RelogA RelogW |
Analýza a relogování
Využití trasování se provádí buď prostřednictvím relace analýzy, nebo relace relogování.
Použití pravidelné analýzy je vhodné pro většinu scénářů. Tato metoda poskytuje flexibilitu při výběru výstupního formátu: printf
text, xml, JSON, databáze, volání REST atd.
Relogování je určené pro speciální analýzy, které potřebují vytvořit výstupní soubor ETW. Pomocí relogování můžete přeložit události C++ Build Insights do vlastního formátu událostí pro Windows. Vhodné použití relogování by bylo připojit data C++ Build Insights k existujícím nástrojům a infrastruktuře trasování událostí pro Windows. Například vcperf využívá rozhraní pro přelogování. Je to proto, že musí vytvářet data, která nástroj pro Windows Analyzátor výkonu, nástroj pro Windows Pro Windows dokáže pochopit. Některé předchozí znalosti o tom, jak ETW funguje, je potřeba, pokud plánujete používat rozhraní pro přelogování.
Vytváření skupin analyzátorů
Je důležité vědět, jak vytvářet skupiny. Tady je příklad, který ukazuje, jak vytvořit skupinu analyzátorů, která vytiskne Hello, World! pro každou událost zahájení aktivity, kterou obdrží.
using namespace Microsoft::Cpp::BuildInsights;
class Hello : public IAnalyzer
{
public:
AnalysisControl OnStartActivity(
const EventStack& eventStack) override
{
std::cout << "Hello, " << std::endl;
return AnalysisControl::CONTINUE;
}
};
class World : public IAnalyzer
{
public:
AnalysisControl OnStartActivity(
const EventStack& eventStack) override
{
std::cout << "world!" << std::endl;
return AnalysisControl::CONTINUE;
}
};
int main()
{
Hello hello;
World world;
// Let's make Hello the first analyzer in the group
// so that it receives events and prints "Hello, "
// first.
auto group = MakeStaticAnalyzerGroup(&hello, &world);
unsigned numberOfAnalysisPasses = 1;
// Calling this function initiates the analysis and
// forwards all events from "inputTrace.etl" to my analyzer
// group.
Analyze("inputTrace.etl", numberOfAnalysisPasses, group);
return 0;
}
Použití událostí
Typy a funkce sady SDK související s událostmi
Aktivity a jednoduché události
Události mají dvě kategorie: aktivity a jednoduché události. Aktivity jsou probíhající procesy v čase, které mají začátek a konec. Jednoduché události jsou interpunkční výskyty a nemají dobu trvání. Při analýze trasování MSVC pomocí sady C++ Build Insights SDK obdržíte při spuštění a zastavení aktivity samostatné události. Když dojde k jednoduché události, obdržíte pouze jednu událost.
Vztahy nadřazenosti a podřízenosti
Aktivity a jednoduché události spolu vzájemně souvisejí prostřednictvím vztahů nadřazenosti a podřízenosti. Nadřazenou aktivitou nebo jednoduchou událostí je zahrnutí aktivity, ve které k nim dochází. Například při kompilaci zdrojového souboru musí kompilátor soubor analyzovat a pak vygenerovat kód. Aktivity analýzy a generování kódu jsou obě podřízené aktivitě kompilátoru.
Jednoduché události nemají dobu trvání, takže se v nich nic jiného nestane. Takhle nikdy nemají žádné děti.
Relace nadřazenosti a podřízenosti jednotlivých aktivit a jednoduché události jsou uvedené v tabulce událostí. Znalost těchto relací je důležitá při využívání událostí C++ Build Insights. Často se na ně budete muset spolehnout, abyste porozuměli úplnému kontextu události.
Vlastnosti
Všechny události mají následující vlastnosti:
Vlastnost | Popis |
---|---|
Identifikátor typu | Číslo, které jednoznačně identifikuje typ události. |
Identifikátor instance | Číslo, které jednoznačně identifikuje událost v rámci trasování. Pokud v trasování dojde ke dvěma událostem stejného typu, oba získají jedinečný identifikátor instance. |
Počáteční čas | Čas zahájení aktivity nebo čas, kdy došlo k jednoduché události. |
Identifikátor procesu | Číslo, které identifikuje proces, ve kterém došlo k události. |
Identifikátor vlákna | Číslo, které identifikuje vlákno, ve kterém došlo k události. |
Index procesoru | Index založený na nule označující, kterým logickým procesorem událost vygeneroval. |
Název události | Řetězec, který popisuje typ události. |
Všechny aktivity kromě jednoduchých událostí mají také tyto vlastnosti:
Vlastnost | Popis |
---|---|
Čas zastavení | Čas, kdy se aktivita zastavila. |
Výhradní doba trvání | Doba strávená v aktivitě, s výjimkou času stráveného ve svých podřízených aktivitách. |
Čas procesoru | Doba, kterou procesor strávil spouštěním kódu ve vlákně připojeném k aktivitě. Nezahrnuje čas, kdy vlákno připojené k aktivitě spí. |
Exkluzivní čas procesoru | Stejné jako čas procesoru, ale s výjimkou času procesoru stráveného podřízenými aktivitami. |
Odpovědnost za čas strávený hodinou | Příspěvek aktivity k celkovému času na nástěnné hodiny. Odpovědnost za nástěnný čas bere v úvahu paralelismus mezi aktivitami. Předpokládejme například, že se paralelně spouští dvě nesouvisející aktivity. Oba mají dobu trvání 10 sekund a přesně stejnou dobu spuštění a zastavení. V tomto případě build Insights přiřazuje odpovědnost za 5 sekund na 5 sekund. Naproti tomu pokud tyto aktivity běží jeden po druhém bez překrytí, oba mají přiřazenou odpovědnost za 10 sekund hodin. |
Výhradní odpovědnost za hodiny | Stejná jako zodpovědnost za hodiny, ale vylučuje odpovědnost za hodiny dětí. |
Některé události mají své vlastní vlastnosti nad rámec zmíněných událostí. V tomto případě jsou tyto další vlastnosti uvedeny v tabulce událostí.
Využívání událostí poskytovaných sadou SDK pro buildy jazyka C++
Zásobník událostí
Pokaždé, když vám sada SDK pro buildy C++ dává událost, přichází ve formě zásobníku. Poslední položka v zásobníku je aktuální událost a položky před ní jsou nadřazenou hierarchií. Například události spuštění a zastavení LTCG probíhají během průchodu 1 linkeru. V tomto případě zásobník, který byste dostali, obsahuje: [LINKER, PASS1, LTCG]. Nadřazená hierarchie je pohodlná, protože můžete trasovat událost do kořenového adresáře. Pokud je výše uvedená aktivita LTCG pomalá, můžete okamžitě zjistit, které vyvolání linkeru se týká.
Odpovídající události a zásobníky událostí
Sada SDK C++ Build Insights poskytuje každou událost v trasování, ale ve většině případů vám záleží jenom na jejich podmnožině. V některých případech se můžete starat pouze o podmnožinu zásobníků událostí. Sada SDK poskytuje možnosti, které vám pomůžou rychle extrahovat události nebo zásobník událostí, které potřebujete, a odmítnout ty, které nepotřebujete. Provádí se prostřednictvím těchto odpovídajících funkcí:
Function | Popis |
---|---|
MatchEvent | Pokud odpovídá některému ze zadaných typů, zachovejte událost. Přeposlání odpovídajících událostí na lambda nebo jiný typ volatelný. Nadřazená hierarchie události není touto funkcí považována. |
MatchEventInMemberFunction | Pokud odpovídá typu zadanému v parametru členské funkce, ponechte událost. Přeposlání odpovídajících událostí členské funkci Nadřazená hierarchie události není touto funkcí považována. |
MatchEventStack | Pokud událost i nadřazená hierarchie odpovídají zadaným typům, ponechte událost. Přesměrujte událost a odpovídající události nadřazené hierarchie na lambda nebo jiný typ volatelného typu. |
MatchEventStackInMemberFunction | Pokud událost i nadřazená hierarchie odpovídají typům zadaným v seznamu parametrů členské funkce, ponechte událost. Přeposlání události a odpovídajících nadřazených hierarchických událostí členské funkci. |
Odpovídající funkce zásobníku událostí, jako je MatchEventStack
například povolit mezery při popisu nadřazené hierarchie, aby se shodovaly. Můžete například říct, že vás zajímá zásobník [LINKER, LTCG]. Také by odpovídal zásobníku [LINKER, PASS1, LTCG]. Poslední zadaný typ musí být typ události, který se má shodovat a není součástí nadřazené hierarchie.
Třídy zachytávání
Match*
Použití funkcí vyžaduje, abyste zadali typy, které se mají shodovat. Tyto typy jsou vybrány ze seznamu tříd zachycení. Třídy zachycení mají několik kategorií, které jsou popsané níže.
Kategorie | Popis |
---|---|
Přesný | Tyto třídy zachycení slouží ke shodě s konkrétním typem události a žádnou jinou. Příkladem je třída kompilátoru, která odpovídá události COMPILER. |
Divoká karta | Tyto třídy zachytávání se dají použít ke spárování jakékoli události ze seznamu událostí, které podporují. Zástupný znak aktivity například odpovídá události aktivity. Dalším příkladem je zástupný znak CompilerPass , který může odpovídat FRONT_END_PASS nebo události BACK_END_PASS . |
Seskupit | Názvy tříd zachycení skupin končí ve skupině. Slouží k porovnávání více událostí stejného typu v řádku a ignoruje mezery. Mají smysl jenom při porovnávání rekurzivních událostí, protože nevíte, kolik existuje v zásobníku událostí. Například aktivita FRONT_END_FILE probíhá pokaždé, když kompilátor analyzuje soubor. Tato aktivita je rekurzivní, protože kompilátor může při analýze souboru najít direktivu include. Třída FrontEndFile odpovídá pouze jedné FRONT_END_FILE události v zásobníku. Pomocí třídy FrontEndFileGroup se shoduje s celou hierarchií zahrnutí. |
Skupina zástupných znaků | Skupina zástupných znaků kombinuje vlastnosti zástupných znaků a skupin. Jedinou třídou této kategorie je InvocationGroup, která odpovídá a zachycuje všechny události LINKER a COMPILER v jediném zásobníku událostí. |
V tabulce událostí se dozvíte, které třídy zachytávání se dají použít k porovnání jednotlivých událostí.
Po porovnávání: použití zachycených událostí
Jakmile se shoda úspěšně dokončí, Match*
funkce sestaví objekty třídy capture a předají je zadané funkci. Tyto objekty třídy zachycení použijte pro přístup k vlastnostem událostí.
Příklad
AnalysisControl MyAnalyzer::OnStartActivity(const EventStack& eventStack)
{
// The event types to match are specified in the PrintIncludes function
// signature.
MatchEventStackInMemberFunction(eventStack, this, &MyAnalyzer::PrintIncludes);
}
// We want to capture event stacks where:
// 1. The current event is a FrontEndFile activity.
// 2. The current FrontEndFile activity has at least one parent FrontEndFile activity
// and possibly many.
void PrintIncludes(FrontEndFileGroup parentIncludes, FrontEndFile currentFile)
{
// Once we reach this point, the event stack we are interested in has been matched.
// The current FrontEndFile activity has been captured into 'currentFile', and
// its entire inclusion hierarchy has been captured in 'parentIncludes'.
cout << "The current file being parsed is: " << currentFile.Path() << endl;
cout << "This file was reached through the following inclusions:" << endl;
for (auto& f : parentIncludes)
{
cout << f.Path() << endl;
}
}