Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
O C++ Build Insights SDK é compatível com o Visual Studio 2017 e posterior. Para ver a documentação destas versões, defina o controlo seletor de versão do Visual Studio para este artigo para Visual Studio 2017 ou posterior. Encontra-se na parte superior do índice desta página.
O C++ Build Insights SDK é uma coleção de APIs que permitem criar ferramentas personalizadas sobre a plataforma C++ Build Insights. Esta página fornece uma visão geral de alto nível para ajudá-lo a começar.
Obtendo o SDK
Você pode baixar o C++ Build Insights SDK como um pacote NuGet seguindo estas etapas:
- No Visual Studio 2017 e superior, crie um novo projeto C++.
- No painel Gerenciador de Soluções , clique com o botão direito do mouse em seu projeto.
- Selecione Gerenciar pacotes NuGet no menu de contexto.
- No canto superior direito, selecione a nuget.org origem do pacote.
- Procure a versão mais recente do pacote Microsoft.Cpp.BuildInsights.
- Escolha Instalar.
- Aceite a licença.
Continue lendo para obter informações sobre os conceitos gerais que envolvem o SDK. Você também pode acessar o repositório oficial do GitHub de amostras do C++ Build Insights para ver exemplos de aplicativos C++ reais que usam o SDK.
Recolha de um vestígio
Usar o C++ Build Insights SDK para analisar eventos que saem da cadeia de ferramentas MSVC requer que você primeiro colete um rastreamento. O SDK usa o Rastreamento de Eventos para Windows (ETW) como a tecnologia de rastreamento subjacente. A recolha de um vestígio pode ser feita de duas formas:
Método 1: usando vcperf no Visual Studio 2019 e superior
Abra um prompt de comando de ferramentas nativas x64 elevado para o VS 2019.
Execute o seguinte comando:
vcperf /start MySessionNameConstrua o seu projeto.
Execute o seguinte comando:
vcperf /stopnoanalyze MySessionName outputTraceFile.etlImportante
Utilize o comando
/stopnoanalyzeao parar o seu rastreamento com vcperf. Não é possível usar o C++ Build Insights SDK para analisar rastreamentos interrompidos pelo comando regular/stop.
Método 2: programaticamente
Use qualquer uma dessas funções de coleta de rastreamento do C++ Build Insights SDK para iniciar e parar rastreamentos programaticamente. O programa que executa essas chamadas de função deve ter privilégios administrativos. Somente as funções de rastreamento de início e fim exigem privilégios administrativos. Todas as outras funções no C++ Build Insights SDK podem ser executadas sem elas.
Funções do SDK relacionadas com a recolha de traços
| Funcionalidade | C++ API | C API |
|---|---|---|
| Iniciando um rastreamento | StartTracingSession |
StartTracingSessionA StartTracingSessionW |
| Parar um rastreio | StopTracingSession |
StopTracingSessionA StopTracingSessionW |
| Parar um rastreio e analisar imediatamente o resultado |
StopAndAnalyzeTracingSession |
StopAndAnalyzeTracingSessionA StopAndAnalyzeTracingSession |
| Parar um rastreio e reregistrando imediatamente o resultado |
StopAndRelogTracingSession |
StopAndRelogTracingSessionA StopAndRelogTracingSessionW |
As secções seguintes mostram como configurar uma análise ou uma sessão de relogging. É necessário para as funções de funcionalidade combinadas, como StopAndAnalyzeTracingSession.
Consumir um vestígio
Depois de ter um rastreamento ETW, use o C++ Build Insights SDK para descompactá-lo. O SDK oferece os eventos em um formato que permite que você desenvolva suas ferramentas rapidamente. Não recomendamos consumir o traço ETW bruto sem usar o SDK. O formato de evento usado pelo MSVC não é documentado, otimizado para ser dimensionado para grandes compilações e difícil de entender. Além disso, a API do SDK do C++ Build Insights é estável, enquanto o formato de rastreamento ETW bruto está sujeito a alterações sem aviso prévio.
Tipos de SDK e funções relacionadas com o consumo de traços
| Funcionalidade | C++ API | C API | Observações |
|---|---|---|---|
| Configurando callbacks de eventos |
IAnalyzer IRelogger |
ANALYSIS_CALLBACKS RELOG_CALLBACKS |
O C++ Build Insights SDK fornece eventos através de funções de callback. Em C++, implemente as funções de callback criando uma classe de analisador ou relogger que herda da interface IAnalyzer ou IRelogger. Em C, implemente os retornos de chamada em funções globais e forneça ponteiros para eles na estrutura ANALYSIS_CALLBACKS ou RELOG_CALLBACKS. |
| Grupos de construção |
MakeStaticAnalyzerGroup MakeStaticReloggerGroup MakeDynamicAnalyzerGroup MakeDynamicReloggerGroup |
A API C++ fornece funções e tipos auxiliares para agrupar vários objetos do analisador e do relogger. Os grupos são uma boa maneira de dividir uma análise complexa em etapas mais simples. O VCPERF está organizado desta forma. | |
| Analisando ou reregistrando |
Analisar Relog |
AnalisaA AnalisarW RelogA RelogW |
Analisando e efetuando novo registo
O consumo de um rastreamento é feito por meio de uma sessão de análise ou de uma sessão de reregistro.
O uso de uma análise regular é apropriado para a maioria dos cenários. Esse método oferece a flexibilidade de escolher o formato de saída: printf texto, xml, JSON, banco de dados, chamadas REST e assim por diante.
Relogging é para análises de fins especiais que precisam produzir um arquivo de saída ETW. Usando o relogging, você pode traduzir os eventos do C++ Build Insights em seu próprio formato de evento ETW. Um uso apropriado do relogging seria conectar os dados do C++ Build Insights às suas ferramentas e infraestrutura ETW existentes. Por exemplo, vcperf faz uso das interfaces de relogging. Isso porque ele deve produzir dados que o Windows Performance Analyzer, uma ferramenta ETW, possa entender. É necessário algum conhecimento prévio de como o ETW funciona caso pretenda usar as interfaces de regravação.
Criação de grupos de analisadores
É importante saber como criar grupos. Aqui está um exemplo que mostra como criar um grupo de analisadores que imprime Olá, mundo! para cada evento de início de atividade que recebe.
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;
}
Usando eventos
Tipos de SDK e funções relacionadas a eventos
Atividades e eventos simples
Os eventos dividem-se em duas categorias: atividades e eventos simples. As atividades são processos contínuos no tempo que têm um começo e um fim. Eventos simples são ocorrências pontuais e não têm duração. Ao analisar rastreamentos MSVC com o C++ Build Insights SDK, você receberá eventos separados quando uma atividade for iniciada e interrompida. Você receberá apenas um evento quando ocorrer um evento simples.
Relações entre pais e filhos
Atividades e eventos simples estão relacionados entre si através de relações entre pais e filhos. O pai de uma atividade ou evento simples é a atividade abrangente na qual eles ocorrem. Por exemplo, ao compilar um arquivo de origem, o compilador tem que analisar o arquivo e, em seguida, gerar o código. As atividades de análise e geração de código são ambas filhas da atividade do compilador.
Eventos simples não têm duração, então nada mais pode acontecer dentro deles. Como tal, nunca têm filhos.
As relações pai-filho de cada atividade e evento simples são indicadas na tabela de eventos. Conhecer esses relacionamentos é importante ao consumir eventos do C++ Build Insights. Muitas vezes, você terá que confiar neles para entender o contexto completo de um evento.
Propriedades
Todos os eventos têm as seguintes propriedades:
| Propriedade | Descrição |
|---|---|
| Identificador de tipo | Um número que identifica exclusivamente o tipo de evento. |
| Identificador de instância | Um número que identifica exclusivamente o evento dentro do rasto. Se dois eventos do mesmo tipo ocorrerem em um rastreamento, ambos obterão um identificador de instância exclusivo. |
| Hora de início | A hora em que uma atividade começou ou a hora em que um evento simples ocorreu. |
| Identificador do processo | Um número que identifica o processo em que o evento ocorreu. |
| Identificador de thread | Um número que identifica o thread no qual o evento ocorreu. |
| Índice do processador | Um índice baseado em zero que indica por qual processador lógico o evento foi emitido. |
| Nome do evento | Uma cadeia de caracteres que descreve o tipo de evento. |
Todas as atividades que não sejam eventos simples também têm estas propriedades:
| Propriedade | Descrição |
|---|---|
| Parar o tempo | A hora em que a atividade parou. |
| Duração exclusiva | O tempo gasto em uma atividade, excluindo o tempo gasto em suas atividades infantis. |
| Tempo de CPU | O tempo que a CPU gastou executando código no thread anexado à atividade. Não inclui o tempo em que o fio ligado à atividade estava dormindo. |
| Tempo exclusivo de CPU | O mesmo que o tempo da CPU, mas excluindo o tempo da CPU gasto pelas atividades da criança. |
| Responsabilidade pelo tempo do relógio de parede | A contribuição da atividade para o tempo total do relógio de parede. A responsabilidade pelo tempo de relógio de parede leva em conta o paralelismo entre as atividades. Por exemplo, vamos supor que duas atividades não relacionadas sejam executadas em paralelo. Ambos têm uma duração de 10 segundos e exatamente o mesmo tempo de início e parada. Neste caso, o Build Insights atribui a ambos uma responsabilidade de tempo de relógio de parede de 5 segundos. Por outro lado, se essas atividades forem executadas uma após a outra sem sobreposição, ambas receberão uma responsabilidade de tempo de relógio de parede de 10 segundos. |
| Responsabilidade exclusiva pelo tempo do relógio de parede | O mesmo que a responsabilidade do tempo do relógio de parede, mas exclui a responsabilidade do tempo do relógio de parede das atividades infantis. |
Alguns eventos têm propriedades próprias além das mencionadas. Nesse caso, essas propriedades adicionais são listadas na tabela de eventos.
Consumindo eventos fornecidos pelo C++ Build Insights SDK
A pilha de eventos
Sempre que o C++ Build Insights SDK fornece um evento, ele vem na forma de uma pilha. A última entrada na pilha é o evento atual e as entradas antes dela são a sua hierarquia de pai. Por exemplo, os eventos de início e parada do LTCG ocorrem durante a passagem 1 do vinculador. Neste caso, a pilha que você receberia contém: [LINKER, PASS1, LTCG]. A hierarquia pai é conveniente porque você pode rastrear um evento até sua raiz. Se a atividade LTCG mencionada acima for lenta, você poderá saber imediatamente qual invocação de vinculador estava envolvida.
Eventos correspondentes e pilhas de eventos
O C++ Build Insights SDK oferece todos os eventos em um rastreamento, mas na maioria das vezes você só se preocupa com um subconjunto deles. Em alguns casos, você pode se preocupar apenas com um subconjunto de pilhas de eventos. O SDK fornece recursos para ajudá-lo a extrair rapidamente os eventos ou a pilha de eventos de que você precisa e rejeitar os que você não precisa. É feito através destas funções correspondentes:
| Função | Descrição |
|---|---|
| MatchEvent | Mantenha um evento se ele corresponder a um dos tipos especificados. Encaminhe eventos correspondentes para um lambda ou outro tipo chamável. A hierarquia pai do evento não é considerada por essa função. |
| MatchEventInMemberFunction | Mantenha um evento se ele corresponder ao tipo especificado no parâmetro de uma função membro. Encaminhe os eventos correspondentes para a função de membro. A hierarquia pai do evento não é considerada por essa função. |
| MatchEventStack | Mantenha um evento caso tanto o evento quanto a sua hierarquia pai correspondam aos tipos especificados. Encaminhe o evento e os eventos de hierarquia pai correspondentes para um lambda ou outro tipo chamável. |
| MatchEventStackInMemberFunction | Mantenha um evento se o evento e a sua hierarquia parental correspondam aos tipos especificados na lista de parâmetros de uma função membro. Encaminhe o evento e os eventos correspondentes da hierarquia pai para a função de membro. |
As funções de correspondência da pilha de eventos, como MatchEventStack, permitem lacunas quando se descreve a hierarquia pai a ser correspondida. Por exemplo, tu podes dizer que estás interessado na stack [LINKER,LTCG]. Isto também corresponderia à pilha [LINKER, PASS1, LTCG]. O último tipo especificado deve ser o tipo de evento a ser comparado e não faz parte da hierarquia superior.
Classes de captura
O uso das funções Match* requer que especifiques os tipos que desejas que correspondam. Esses tipos são selecionados a partir de uma lista de classes de captura. As classes de captura vêm em várias categorias, descritas abaixo.
| Categoria | Descrição |
|---|---|
| Exato | Essas classes de captura são usadas para corresponder a um tipo de evento específico e nenhum outro. Um exemplo é a classe Compiler , que corresponde ao evento COMPILER . |
| Caráter curinga | Essas classes de captura podem ser usadas para corresponder a qualquer evento da lista de eventos suportados. Por exemplo, o wildcard Atividade corresponde a qualquer evento de atividade. Outro exemplo é o wildcard CompilerPass, que pode corresponder ao evento FRONT_END_PASS ou BACK_END_PASS. |
| Grupo | Os nomes das classes de captura de grupo terminam em Grupo. São usados para combinar vários eventos do mesmo tipo consecutivamente, ignorando intervalos. Eles só fazem sentido ao combinar eventos recursivos, porque você não sabe quantos existem na pilha de eventos. Por exemplo, a atividade FRONT_END_FILE acontece toda vez que o compilador analisa um arquivo. Essa atividade é recursiva porque o compilador pode encontrar uma diretiva include enquanto está analisando o arquivo. A classe FrontEndFile corresponde a apenas um evento FRONT_END_FILE na pilha. Use a classe FrontEndFileGroup para corresponder a toda a hierarquia de inclusão. |
| Grupo comodín | Um grupo curinga combina as propriedades de curinga e de grupo. A única classe dessa categoria é InvocationGroup, que corresponde e captura todos os eventos LINKER e COMPILER em uma única pilha de eventos. |
Consulte a tabela de eventos para saber quais classes de captura podem ser usadas para corresponder a cada evento.
Após a correspondência, utilização de eventos capturados
Quando um jogo é concluído com êxito, as Match* funções constroem os objectos de captura e enviam-nos para a função especificada. Use esses objetos de classe de captura para acessar as propriedades dos eventos.
Exemplo
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;
}
}