Partager via


Kit SDK C++ Build Insights

Le Kit de développement logiciel (SDK) build C++ Recommandations est compatible avec Visual Studio 2017 et versions ultérieures. Pour afficher la documentation de ces versions, définissez le contrôle sélecteur de version Visual Studio pour cet article sur Visual Studio 2017 ou version ultérieure. Il se trouve en haut de la table des matières de cette page.

Le SDK Build C++ Recommandations est une collection d’API qui vous permettent de créer des outils personnalisés en plus de la plateforme build C++ Recommandations. Cette page fournit une vue d’ensemble générale pour vous aider à commencer.

Obtention du Kit de développement logiciel (SDK)

Vous pouvez télécharger le Kit de développement logiciel (SDK) de build C++ Recommandations en tant que package NuGet en procédant comme suit :

  1. À partir de Visual Studio 2017 et versions ultérieures, créez un projet C++.
  2. Dans le volet Explorateur de solutions, cliquez avec le bouton droit sur votre projet.
  3. Sélectionnez Gérer les packages NuGet dans le menu contextuel.
  4. En haut à droite, sélectionnez la source du package nuget.org .
  5. Recherchez la dernière version du package Microsoft.Cpp.Build Recommandations.
  6. Choisissez Installer.
  7. Acceptez la licence.

Pour plus d’informations sur les concepts généraux entourant le Kit de développement logiciel (SDK). Vous pouvez également accéder à la build C++ officielle Recommandations exemples de référentiel GitHub pour voir des exemples d’applications C++ réelles qui utilisent le Kit de développement logiciel (SDK).

Collecte d’une trace

L’utilisation de la build C++ Recommandations SDK pour analyser les événements sortant de la chaîne d’outils MSVC nécessite de commencer par collecter une trace. Le Kit de développement logiciel (SDK) utilise le suivi d’événements pour Windows (ETW) comme technologie de suivi sous-jacente. La collecte d’une trace peut être effectuée de deux manières :

Méthode 1 : utilisation de vcperf dans Visual Studio 2019 et versions ultérieures

  1. Ouvrez une invite de commandes x64 Native Tools avec élévation de privilèges pour VS 2019.

  2. Exécutez la commande suivante : vcperf /start MySessionName

  3. Générez votre projet.

  4. Exécutez la commande suivante : vcperf /stopnoanalyze MySessionName outputTraceFile.etl

    Important

    Utilisez la commande lors de l’arrêt /stopnoanalyze de votre trace avec vcperf. Vous ne pouvez pas utiliser le Kit de développement logiciel (SDK) build C++ Recommandations pour analyser les traces arrêtées par la commande régulière/stop.

Méthode 2 : programmatiquement

Utilisez l’une de ces fonctions de collecte de traces C++ build Recommandations SDK pour démarrer et arrêter les traces par programmation. Le programme qui exécute ces appels de fonction doit avoir des privilèges d’administration. Seules les fonctions de démarrage et d’arrêt du suivi nécessitent des privilèges d’administration. Toutes les autres fonctions du Kit de développement logiciel (SDK) build C++ Recommandations peuvent être exécutées sans elles.

Fonctionnalités API C++ API C
Démarrage d’une trace StartTracingSession StartTracingSessionA
StartTracingSessionW
Arrêt d’une trace StopTracingSession StopTracingSessionA
StopTracingSessionW
Arrêt d’une trace et
Analyse immédiate du résultat
StopAndAnalyzeTracingSession StopAndAnalyzeTracingSessionA
StopAndAnalyzeTracingSession
Arrêt d’une trace et
Relogging immédiatement le résultat
StopAndRelogTracingSession StopAndRelogTracingSessionA
StopAndRelogTracingSessionW

Les sections suivantes vous montrent comment configurer une analyse ou une session de relogging. Il est nécessaire pour les fonctions de fonctionnalité combinées, telles que StopAndAnalyzeTracingSession.

Consommation d’une trace

Une fois que vous avez une trace ETW, utilisez le Kit de développement logiciel (SDK) de build C++ Recommandations pour le décompresser. Le Kit de développement logiciel (SDK) vous donne les événements dans un format qui vous permet de développer rapidement vos outils. Nous vous déconseillons de consommer la trace ETW brute sans utiliser le Kit de développement logiciel (SDK). Le format d’événement utilisé par MSVC n’est pas documenté, optimisé pour être mis à l’échelle vers d’énormes builds et difficile à comprendre. En outre, la build C++ Recommandations API sdk est stable, tandis que le format de trace ETW brut est susceptible de changer sans préavis.

Fonctionnalités API C++ API C Notes
Configuration des rappels d’événements IAnalyzer
IRelogger
ANALYSIS_CALLBACKS
RELOG_CALLBACKS
Le kit SDK build C++ Recommandations fournit des événements via des fonctions de rappel. En C++, implémentez les fonctions de rappel en créant une classe d’analyseur ou de relogger qui hérite de l’interface IAnalyzer ou IRelogger. En C, implémentez les rappels dans les fonctions globales et fournissez des pointeurs vers ceux-ci dans la structure ANALYSIS_CALLBACKS ou RELOG_CALLBACKS.
Création de groupes MakeStaticAnalyzerGroup
MakeStaticReloggerGroup
MakeDynamicAnalyzerGroup
MakeDynamicReloggerGroup
L’API C++ fournit des fonctions d’assistance et des types pour regrouper plusieurs objets d’analyseur et de relogage. Les groupes constituent un moyen simple de diviser une analyse complexe en étapes plus simples. vcperf est organisé de cette façon.
Analyse ou relogging Analyser.
Relog
AnalyzeA
AnalyzeW
RelogA
RelogW

Analyse et relogging

L’utilisation d’une trace est effectuée via une session d’analyse ou une session de relogging.

L’utilisation d’une analyse régulière convient à la plupart des scénarios. Cette méthode vous offre la possibilité de choisir votre format de sortie : printf texte, xml, JSON, base de données, appels REST, et ainsi de suite.

La relogging est destinée aux analyses spéciales qui doivent produire un fichier de sortie ETW. À l’aide de la relogging, vous pouvez traduire les événements build C++ Recommandations dans votre propre format d’événement ETW. Une utilisation appropriée de la relogging serait de connecter C++ Build Recommandations données à vos outils et infrastructures ETW existants. Par exemple, vcperf utilise les interfaces de relogging. C’est parce qu’il doit produire des données que windows Analyseur de performances, un outil ETW, peut comprendre. Certaines connaissances préalables sur le fonctionnement d’ETW sont requises si vous prévoyez d’utiliser les interfaces de relogging.

Création de groupes d’analyseurs

Il est important de savoir comment créer des groupes. Voici un exemple qui montre comment créer un groupe d’analyseurs qui imprime Hello, world ! pour chaque événement de démarrage d’activité qu’il reçoit.

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;
}

Utilisation d’événements

Fonctionnalités API C++ API C Notes
Événements de correspondance et de filtrage MatchEventStackInMemberFunction
MatchEventStack
MatchEventInMemberFunction
MatchEvent
L’API C++ offre des fonctions qui facilitent l’extraction des événements dont vous vous souciez à partir de vos traces. Avec l’API C, ce filtrage doit être effectué manuellement.
Types de données d’événement Activité
BackEndPass
BottomUp
C1DLL
C2DLL
CodeGeneration
CommandLine
Compilateur
CompilerPass
EnvironmentVariable
Événement
EventGroup
EventStack
ExecutableImageOutput
ExpOutput
FileInput
FileOutput
ForceInlinee
FrontEndFile
FrontEndFileGroup
FrontEndPass
Fonction
HeaderUnit
ImpLibOutput
Invocation
InvocationGroup
LibOutput
Linker
LinkerGroup
LinkerPass
LTCG
Module
ObjOutput
OptICF
OptLBR
OptRef
Pass1
Pass2
PrecompiledHeader
PreLTCGOptRef
SimpleEvent
SymbolName
TemplateInstantiation
TemplateInstantiationGroup
Thread
TopDown
TraceInfo
TranslationUnitType
Qui leProgramAnalysis
CL_PASS_DATA
EVENT_COLLECTION_DATA
EVENT_DATA
EVENT_ID
FILE_DATA
FILE_TYPE_CODE
FRONT_END_FILE_DATA
FUNCTION_DATA
FUNCTION_FORCE_INLINEE_DATA
INVOCATION_DATA
INVOCATION_VERSION_DATA
MSVC_TOOL_CODE
NAME_VALUE_PAIR_DATA
SY MoOL_NAME_DATA
TEMPLATE_INSTANTIATION_DATA
TEMPLATE_INSTANTIATION_KIND_CODE
TRACE_INFO_DATA
TRANSLATION_UNIT_PASS_CODE
TRANSLATION_UNIT_TYPE
TRANSLATION_UNIT_TYPE_DATA

Activités et événements simples

Les événements se présentent en deux catégories : les activités et les événements simples. Les activités sont des processus en cours dans le temps qui ont un début et une fin. Les événements simples sont des occurrences ponctuelles et n’ont pas de durée. Lors de l’analyse des traces MSVC avec le Kit de développement logiciel (SDK) build C++ Recommandations, vous recevrez des événements distincts au démarrage et à l’arrêt d’une activité. Vous ne recevrez qu’un seul événement lorsqu’un événement simple se produit.

Relations parent-enfant

Les activités et les événements simples sont liés les uns aux autres par le biais de relations parent-enfant. Le parent d’une activité ou d’un événement simple est l’activité englobante dans laquelle elles se produisent. Par exemple, lors de la compilation d’un fichier source, le compilateur doit analyser le fichier, puis générer le code. Les activités d’analyse et de génération de code sont les deux enfants de l’activité du compilateur.

Les événements simples n’ont pas de durée, donc rien d’autre ne peut se produire à l’intérieur d’eux. Ainsi, ils n’ont jamais d’enfants.

Les relations parent-enfant de chaque activité et événement simple sont indiquées dans la table d’événements. La connaissance de ces relations est importante lors de l’utilisation des événements de build C++ Recommandations. Vous devrez souvent vous appuyer sur eux pour comprendre le contexte complet d’un événement.

Propriétés

Tous les événements ont les propriétés suivantes :

Propriété Description
Identificateur de type Nombre qui identifie de façon unique le type d’événement.
Identificateur d’instance Nombre qui identifie de façon unique l’événement dans la trace. Si deux événements du même type se produisent dans une trace, les deux obtiennent un identificateur d’instance unique.
Heure de début Heure à laquelle une activité a démarré ou l’heure à laquelle un événement simple s’est produit.
Identificateur de processus Nombre qui identifie le processus dans lequel l’événement s’est produit.
Identificateur de thread Nombre qui identifie le thread dans lequel l’événement s’est produit.
Index du processeur Index de base zéro indiquant le processeur logique par lequel l’événement a été émis.
Nom de l’événement Chaîne qui décrit le type d’événement.

Toutes les activités autres que les événements simples ont également ces propriétés :

Propriété Description
Heure d’arrêt Heure à laquelle l’activité s’est arrêtée.
Durée exclusive Temps passé dans une activité, à l’exclusion du temps passé dans ses activités enfants.
Temps processeur Temps passé par l’UC à exécuter du code dans le thread attaché à l’activité. Il n’inclut pas le moment où le thread attaché à l’activité était en veille.
Temps processeur exclusif Identique au temps processeur, mais à l’exclusion du temps processeur passé par les activités enfants.
Responsabilité de l’heure du mur La contribution de l’activité à l’heure globale de l’horloge murale. La responsabilité du temps d’horloge mur prend en compte le parallélisme entre les activités. Par exemple, supposons que deux activités non liées s’exécutent en parallèle. Les deux ont une durée de 10 secondes, et exactement la même heure de début et d’arrêt. Dans ce cas, build Recommandations attribue à la fois une responsabilité de temps de mur de 5 secondes. En revanche, si ces activités s’exécutent l’une après l’autre sans chevauchement, elles sont toutes deux affectées à une responsabilité de temps de mur de 10 secondes.
Responsabilité exclusive de l’heure du mur Identique à la responsabilité de l’heure du mur, mais exclut la responsabilité de l’heure de l’horloge murale des activités enfants.

Certains événements ont leurs propres propriétés au-delà de celles mentionnées. Dans ce cas, ces propriétés supplémentaires sont répertoriées dans la table d’événements.

Consommation d’événements fournis par le Kit de développement logiciel (SDK) build C++ Recommandations

Pile d’événements

Chaque fois que le Kit de développement logiciel (SDK) build C++ Recommandations vous donne un événement, il se présente sous la forme d’une pile. La dernière entrée de la pile est l’événement actuel et les entrées avant qu’elles ne soient sa hiérarchie parente. Par exemple, les événements de démarrage et d’arrêt LTCG se produisent pendant la passe 1 de l’éditeur de liens. Dans ce cas, la pile que vous recevez contient : [LINKER, PASS1, LTCG]. La hiérarchie parente est pratique, car vous pouvez tracer un événement à sa racine. Si l’activité LTCG mentionnée ci-dessus est lente, vous pouvez immédiatement apprendre quel appel de l’éditeur de liens a été impliqué.

Événements et piles d’événements correspondants

Le Kit de développement logiciel (SDK) build C++ Recommandations vous donne chaque événement dans une trace, mais la plupart du temps, vous vous souciez uniquement d’un sous-ensemble d’entre eux. Dans certains cas, vous pouvez uniquement vous soucier d’un sous-ensemble de piles d’événements. Le Kit de développement logiciel (SDK) fournit des fonctionnalités pour vous aider à extraire rapidement les événements ou la pile d’événements dont vous avez besoin et à rejeter ceux que vous n’avez pas. Elle est effectuée par le biais de ces fonctions correspondantes :

Fonction Description
MatchEvent Conservez un événement s’il correspond à l’un des types spécifiés. Transférer les événements mis en correspondance vers un type lambda ou autre pouvant être appelé. La hiérarchie parente de l’événement n’est pas considérée par cette fonction.
MatchEventInMemberFunction Conservez un événement s’il correspond au type spécifié dans le paramètre d’une fonction membre. Transférer les événements mis en correspondance à la fonction membre. La hiérarchie parente de l’événement n’est pas considérée par cette fonction.
MatchEventStack Conservez un événement si l’événement et sa hiérarchie parente correspondent aux types spécifiés. Transférez l’événement et les événements de hiérarchie parente mis en correspondance vers un type lambda ou autre pouvant être appelé.
MatchEventStackInMemberFunction Conservez un événement si l’événement et sa hiérarchie parente correspondent aux types spécifiés dans la liste de paramètres d’une fonction membre. Transférez l’événement et les événements de hiérarchie parente correspondants à la fonction membre.

Les fonctions de correspondance de la pile d’événements, comme MatchEventStack autoriser les lacunes lors de la description de la hiérarchie parente, correspondent. Par exemple, vous pouvez dire que vous êtes intéressé par la pile [LINKER, LTCG]. Il correspond également à la pile [LINKER, PASS1, LTCG]. Le dernier type spécifié doit être le type d’événement à mettre en correspondance et ne fait pas partie de la hiérarchie parente.

Classes de capture

L’utilisation des Match* fonctions nécessite que vous spécifiiez les types que vous souhaitez mettre en correspondance. Ces types sont sélectionnés dans une liste de classes de capture. Les classes de capture se présentent dans plusieurs catégories, décrites ci-dessous.

Category Description
Exact Ces classes de capture sont utilisées pour faire correspondre un type d’événement spécifique et aucune autre. Par exemple, la classe compiler correspond à l’événement COMPILER .
Caractère générique Ces classes de capture peuvent être utilisées pour faire correspondre n’importe quel événement de la liste des événements qu’ils prennent en charge. Par exemple, l’activité sauvage carte correspond à n’importe quel événement d’activité. Un autre exemple est le caractère générique CompilerPass carte, qui peut correspondre à l’FRONT_END_PASS ou à l’événement de BACK_END_PASS.
Groupe Les noms des classes de capture de groupe se terminent par Groupe. Ils sont utilisés pour faire correspondre plusieurs événements du même type dans une ligne, ignorant les lacunes. Ils n’ont de sens que lors de la correspondance d’événements récursifs, car vous ne savez pas combien existent dans la pile d’événements. Par exemple, l’activité FRONT_END_FILE se produit chaque fois que le compilateur analyse un fichier. Cette activité est récursive, car le compilateur peut trouver une directive Include pendant l’analyse du fichier. La classe FrontEndFile ne correspond qu’à un seul événement FRONT_END_FILE dans la pile. Utilisez la classe FrontEndFileGroup pour correspondre à l’ensemble de la hiérarchie include.
Groupe Wild carte Un groupe wild carte combine les propriétés des groupes et des carte génériques. La seule classe de cette catégorie est InvocationGroup, qui correspond à et capture tous les événements LINKER et COMPILER dans une pile d’événements unique.

Reportez-vous à la table d’événements pour savoir quelles classes de capture peuvent être utilisées pour correspondre à chaque événement.

Après la correspondance : utilisation d’événements capturés

Une fois qu’une correspondance est terminée, les Match* fonctions construisent les objets de classe de capture et les transfèrent à la fonction spécifiée. Utilisez ces objets de classe de capture pour accéder aux propriétés des événements.

Exemple

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;
    }
}