Обучение
Пътека за обучение
Use advance techniques in canvas apps to perform custom updates and optimization - Training
Use advance techniques in canvas apps to perform custom updates and optimization
Този браузър вече не се поддържа.
Надстройте до Microsoft Edge, за да се възползвате от най-новите функции, актуализации на защитата и техническа поддръжка.
The C++ Build Insights SDK is compatible with Visual Studio 2017 and later. To see the documentation for these versions, set the Visual Studio Version selector control for this article to Visual Studio 2017 or later. It's found at the top of the table of contents on this page.
The C++ Build Insights SDK is a collection of APIs that allow you to create personalized tools on top of the C++ Build Insights platform. This page provides a high-level overview to help you get started.
You can download the C++ Build Insights SDK as a NuGet package by following these steps:
Read on for information about the general concepts surrounding the SDK. You can also access the official C++ Build Insights samples GitHub repository to see examples of real C++ applications that use the SDK.
Using the C++ Build Insights SDK to analyze events coming out of the MSVC toolchain requires that you first collect a trace. The SDK makes use of Event Tracing for Windows (ETW) as the underlying tracing technology. Collecting a trace can be done in two ways:
Open an elevated x64 Native Tools Command Prompt for VS 2019.
Run the following command: vcperf /start MySessionName
Build your project.
Run the following command: vcperf /stopnoanalyze MySessionName outputTraceFile.etl
Важно
Use the /stopnoanalyze
command when stopping your trace with vcperf. You can't use the C++ Build Insights SDK to analyze traces stopped by the regular /stop
command.
Use any of these C++ Build Insights SDK trace collection functions to start and stop traces programmatically. The program that executes these function calls must have administrative privileges. Only the start and stop tracing functions require administrative privileges. All other functions in the C++ Build Insights SDK can be executed without them.
Functionality | C++ API | C API |
---|---|---|
Starting a trace | StartTracingSession | StartTracingSessionA StartTracingSessionW |
Stopping a trace | StopTracingSession | StopTracingSessionA StopTracingSessionW |
Stopping a trace and immediately analyzing the result |
StopAndAnalyzeTracingSession | StopAndAnalyzeTracingSessionA StopAndAnalyzeTracingSession |
Stopping a trace and immediately relogging the result |
StopAndRelogTracingSession | StopAndRelogTracingSessionA StopAndRelogTracingSessionW |
The sections that follow show you how to configure an analysis or a relogging session. It's required for the combined functionality functions, such as StopAndAnalyzeTracingSession.
Once you have an ETW trace, use the C++ Build Insights SDK to unpack it. The SDK gives you the events in a format that allows you to develop your tools quickly. We don't recommend you consume the raw ETW trace without using the SDK. The event format used by MSVC is undocumented, optimized to scale to huge builds, and hard to make sense of. Additionally, the C++ Build Insights SDK API is stable, while the raw ETW trace format is subject to change without notice.
Functionality | C++ API | C API | Notes |
---|---|---|---|
Setting up event callbacks | IAnalyzer IRelogger |
ANALYSIS_CALLBACKS RELOG_CALLBACKS |
The C++ Build Insights SDK provides events through callback functions. In C++, implement the callback functions by creating an analyzer or relogger class that inherits the IAnalyzer or IRelogger interface. In C, implement the callbacks in global functions and provide pointers to them in the ANALYSIS_CALLBACKS or RELOG_CALLBACKS structure. |
Building groups | MakeStaticAnalyzerGroup MakeStaticReloggerGroup MakeDynamicAnalyzerGroup MakeDynamicReloggerGroup |
The C++ API provides helper functions and types to group multiple analyzer and relogger objects together. Groups are a neat way to divide a complex analysis into simpler steps. vcperf is organized in this way. | |
Analyzing or relogging | Analyze Relog |
AnalyzeA AnalyzeW RelogA RelogW |
Consuming a trace is done through either an analysis session or a relogging session.
Using a regular analysis is appropriate for most scenarios. This method gives you the flexibility to choose your output format: printf
text, xml, JSON, database, REST calls, and so on.
Relogging is for special-purpose analyses that need to produce an ETW output file. Using relogging, you can translate the C++ Build Insights events into your own ETW event format. An appropriate use of relogging would be to hook C++ Build Insights data to your existing ETW tools and infrastructure. For example, vcperf makes use of the relogging interfaces. That's because it must produce data the Windows Performance Analyzer, an ETW tool, can understand. Some prior knowledge of how ETW works is required if you plan on using the relogging interfaces.
It's important to know how to create groups. Here's an example that shows how to create an analyzer group that prints Hello, world! for every activity start event it receives.
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;
}
Events come in two categories: activities and simple events. Activities are ongoing processes in time that have a beginning and an end. Simple events are punctual occurrences and don't have a duration. When analyzing MSVC traces with the C++ Build Insights SDK, you'll receive separate events when an activity starts and stops. You'll receive only one event when a simple event occurs.
Activities and simple events are related to each other via parent-child relationships. The parent of an activity or simple event is the encompassing activity in which they occur. For example, when compiling a source file the compiler has to parse the file, then generate the code. The parsing and code generation activities are both children of the compiler activity.
Simple events don't have a duration, so nothing else can happen inside them. As such, they never have any children.
The parent-child relationships of each activity and simple event are indicated in the event table. Knowing these relationships is important when consuming C++ Build Insights events. You'll often have to rely on them to understand the full context of an event.
All events have the following properties:
Property | Description |
---|---|
Type identifier | A number that uniquely identifies the event type. |
Instance identifier | A number that uniquely identifies the event within the trace. If two events of the same type occur in a trace, both get a unique instance identifier. |
Start time | The time when an activity started, or the time when a simple event occurred. |
Process identifier | A number that identifies the process in which the event occurred. |
Thread identifier | A number that identifies the thread in which the event occurred. |
Processor index | A zero-based index indicating which logical processor the event was emitted by. |
Event name | A string that describes the event type. |
All activities other than simple events also have these properties:
Property | Description |
---|---|
Stop time | The time when the activity stopped. |
Exclusive duration | The time spent in an activity, excluding the time spent in its child activities. |
CPU time | The time that the CPU spent executing code in the thread attached to the activity. It doesn't include time when the thread attached to the activity was sleeping. |
Exclusive CPU time | Same as CPU time, but excluding the CPU time spent by child activities. |
Wall-clock time responsibility | The activity's contribution to overall wall-clock time. Wall-clock time responsibility takes into account parallelism between activities. For example, let's assume two unrelated activities run in parallel. Both have a duration of 10 seconds, and exactly the same start and stop time. In this case, Build Insights assigns both a wall-clock time responsibility of 5 seconds. In contrast, if these activities run one after the other with no overlap, they're both assigned a wall-clock time responsibility of 10 seconds. |
Exclusive wall-clock time responsibility | Same as wall-clock time responsibility, but excludes the wall-clock time responsibility of child activities. |
Some events have their own properties beyond the ones mentioned. In this case, these additional properties are listed in the event table.
Whenever the C++ Build Insights SDK gives you an event, it comes in the form of a stack. The last entry in the stack is the current event, and entries before it are its parent hierarchy. For example, LTCG start and stop events occur during pass 1 of the linker. In this case, the stack you'd receive contains: [LINKER, PASS1, LTCG]. The parent hierarchy is convenient because you can trace back an event to its root. If the LTCG activity mentioned above is slow, you can immediately learn which linker invocation was involved.
The C++ Build Insights SDK gives you every event in a trace, but most of the time you only care about a subset of them. In some cases, you may only care about a subset of event stacks. The SDK provides facilities to help you quickly extract the events or event stack you need, and reject the ones you don't. It's done through these matching functions:
Function | Description |
---|---|
MatchEvent | Keep an event if it matches one of the specified types. Forward matched events to a lambda or other callable type. The event's parent hierarchy isn't considered by this function. |
MatchEventInMemberFunction | Keep an event if it matches the type specified in a member function's parameter. Forward matched events to the member function. The event's parent hierarchy isn't considered by this function. |
MatchEventStack | Keep an event if both the event and its parent hierarchy match the types specified. Forward the event and the matched parent hierarchy events to a lambda or other callable type. |
MatchEventStackInMemberFunction | Keep an event if both the event and its parent hierarchy match the types specified in a member function's parameter list. Forward the event and the matched parent hierarchy events to the member function. |
The event stack matching functions like MatchEventStack
allow gaps when describing the parent hierarchy to match. For example, you can say you're interested in the [LINKER, LTCG] stack. It would also match the [LINKER, PASS1, LTCG] stack. The last type specified must be the event type to match, and isn't part of the parent hierarchy.
Using the Match*
functions requires that you specify the types you want to match. These types are selected from a list of capture classes. Capture classes come in several categories, described below.
Category | Description |
---|---|
Exact | These capture classes are used to match a specific event type and none other. An example is the Compiler class, which matches the COMPILER event. |
Wildcard | These capture classes can be used to match any event from the list of events they support. For example, the Activity wildcard matches any activity event. Another example is the CompilerPass wildcard, which can match either the FRONT_END_PASS or the BACK_END_PASS event. |
Group | The names of group capture classes end in Group. They're used to match multiple events of the same type in a row, ignoring gaps. They only make sense when matching recursive events, because you don't know how many exist in the event stack. For example, the FRONT_END_FILE activity happens every time the compiler parses a file. This activity is recursive because the compiler may find an include directive while it's parsing the file. The FrontEndFile class matches only one FRONT_END_FILE event in the stack. Use the FrontEndFileGroup class to match the entire include hierarchy. |
Wildcard group | A wildcard group combines the properties of wildcards and groups. The only class of this category is InvocationGroup, which match and capture all LINKER and COMPILER events in a single event stack. |
Refer to the event table to learn which capture classes can be used to match each event.
Once a match completes successfully, the Match*
functions construct the capture class objects and forward them to the specified function. Use these capture class objects to access the events' properties.
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;
}
}
Обучение
Пътека за обучение
Use advance techniques in canvas apps to perform custom updates and optimization - Training
Use advance techniques in canvas apps to perform custom updates and optimization
Документация
Learn how to use C++ Build Insights to analyze and optimize your builds.
Troubleshoot function inlining on build time
Tutorial for how to use Build Insights function view to troubleshoot the impact of function inlining on build time in your C++ projects.
Get started with C++ Build Insights
A high-level overview of C++ Build Insights.