Skip to content

Commit d379660

Browse files
committed
draft work
1 parent cbdce9b commit d379660

File tree

4 files changed

+111
-39
lines changed

4 files changed

+111
-39
lines changed

docs/build-insights/toc.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ items:
88
items:
99
- name: "Troubleshoot function inlining on build time"
1010
href: ../build-insights/tutorials/build-insights-function-view.md
11-
- name: "Analyze template instantiations to optimize build time"
11+
- name: "Troubleshoot template instantiation impact on build time"
1212
href: ../build-insights/tutorials/build-insights-template-view.md
1313
- name: "Troubleshoot header file impact on build time"
1414
href: ../build-insights/tutorials/build-insights-included-files-view.md

docs/build-insights/tutorials/build-insights-template-view.md

Lines changed: 110 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,34 @@ ms.topic: troubleshooting-general
77
---
88
# Troubleshoot template instantiation impact on build time
99

10-
Use Build Insights **Templates** view to analyze the impact of template instantiations on build time in your C++ projects. This feature is especially useful for projects that make heavy use of templates, such as those using template metaprogramming or large generic libraries.
10+
Use Build Insights **Templates** view to analyze the impact of template instantiations on C++ build time. This feature is especially useful for projects that make heavy use of templates, such as those using template metaprogramming or large generic libraries.
11+
12+
Templates view is designed to be familiar to users of the [Functions view](build-insights-function-view.md), with similar UI and workflow.
1113

1214
## Prerequisites
1315

1416
- Visual Studio 2022 version 17.10 or later.
15-
- The **C++ Build Insights** component must be installed. It's enabled by default if you install either the Desktop development with C++ workload or the Game development with C++ workload. You can ensure that it is installed by following these steps:
17+
- The **C++ Build Insights** component must be installed. It's installed as part of either the Desktop development with C++ workload or the Game development with C++ workload. You can ensure that it is installed by following these steps:
1618
1. Open the Visual Studio Installer.
17-
1. Modify your Visual Studio installation.
18-
1. Under the **Individual components** tab, search for and select **C++ Build Insights**.
19+
1. Choose to modify your Visual Studio installation.
20+
1. Under the **Individual components** tab, search for and then select **C++ Build Insights**.
1921
:::image type="complex" source="./media/installer-build-insights.png" alt-text="Screenshot of the Visual Studio Installer":::The search box contains C++ build insights. The item C++ Build Insights is visible and selected.":::image-end:::
2022
1. Click **Modify** to install the component.
2123

2224
## Overview
2325

2426
Build Insights, integrated into Visual Studio, helps you optimize your build times--especially for large projects like AAA games. Build Insights provides analytics such as **Templates** view, which helps diagnose expensive template instantiations during build time. It displays the time it takes to instantiate each template and shows which template instantiations add the most to your build time.
2527

26-
For optimized builds, the time spent on template instantiation contributes significantly to the total build time. In general, C++ template instantiation happens quickly. In exceptional cases, some template instantiations can become complex enough to noticeably slow down your builds.
28+
For optimized builds, the time spent on template instantiation contributes significantly to the total build time. In general, C++ template instantiation happens quickly. In exceptional cases, some template instantiations can noticeably slow down your builds.
2729

2830
In this article, learn how to use the Build Insights **Templates** view to find template instantiation bottlenecks in your build.
2931

30-
To try out Build Insights Templates view, follow along to create a project, set the build options, do a build, and analyze the results.
32+
Follow along to create a project that demonstrates template instantiation, run Build Insights to gather template instantiation times, and analyze the results.
3133

32-
## Create a test project
34+
## Create a template test project
3335

3436
1. Open Visual Studio and create a new **C++ Console App** project and name it `TemplateAnalysis`.
35-
1. Create a header file called `Templates.h`.
36-
1. Replace the contents of the `Templates.h` file with the following code:
37+
1. Create a header file called `Templates.h` and replace its contents with the following code:
3738

3839
```cpp
3940
#pragma once
@@ -64,8 +65,7 @@ To try out Build Insights Templates view, follow along to create a project, set
6465
}
6566
```
6667

67-
1. Create a source file called `LargeValue.cpp`
68-
1. Replace the contents of the `LargeValue.cpp` file with the following code:
68+
1. Create a source file called `LargeValue.cpp` and replace its contents with the following code:
6969

7070
```cpp
7171
#include "Templates.h"
@@ -96,52 +96,127 @@ To try out Build Insights Templates view, follow along to create a project, set
9696
}
9797
```
9898

99-
1. ## Enable template instantiation data collection
99+
## Enable build time data collection
100100

101101
Template instantiation time collection is off by default to minimize build overhead. To enable it:
102102

103103
1. In Visual Studio, go to **Tools** > **Options**.
104-
1. In the Options dialog, expand **Build Insights** in the left navigation.
104+
1. In the **Options** dialog, expand **Build Insights** in the left navigation.
105105
1. Select **Collect Template Instantiation**.
106-
1. You can also choose where to save the report by selecting **Store Build Insights reports in this directory:** and specifying a directory. By default, it's saved in the folder pointed to by the Windows `TEMP` environment variable.
106+
1. You can also choose where to save the report by selecting **Store Build Insights reports in this directory** and specifying a directory. By default, it's saved in the folder pointed to by the Windows `TEMP` environment variable.
107+
1. Select **OK**.
107108

108109
:::image type="content" source="./media/tools-options-build-insights.png" alt-text="Screenshot of the project property pages dialog. The settings are open to Build Insights > Trace Collection. The Collect Template Instantion checkbox is selected.":::
109110

110-
1. Select **OK**.
111-
112111
> [!Note]
113-
> Enabling Templates view may increase build time due to the extra data collected. Only enable it when you need to analyze template instantiations.
112+
> Collecting template instantiation times may increase build time due to the extra data collected. Only enable it when you want to analyze template instantiation bottlenecks.
114113
115-
## Build the project
114+
## Run Build Insights to get template instantiation times
116115

117-
Run Build Insights by choosing from the main menu **Build** > **Run Build Insights on Selection** > **Rebuild**. You can also right-click a project in the solution explorer and choose **Run Build Insights** > **Rebuild**. Choose **Rebuild** instead of **Build** to measure the build time for the entire project and not for just the few files may be dirty right now.
116+
From the main menu, select **Build** > **Run Build Insights on Selection** > **Rebuild**. You can also right-click a project in the solution explorer and choose **Run Build Insights** > **Rebuild**. Choose **Rebuild** instead of **Build** to measure the build time for the entire project.
118117

119118
:::image type="content" source="./media/build-insights-rebuild-project.png" alt-text="Screenshot of the main menu with Run Build Insights on Selection > Rebuild selected.":::
120119

121120
When the build finishes, an Event Trace Log (ETL) file opens.The generated name is based on the collection time.
122121

123-
## Use Templates View to Optimize Build Time
122+
## Use Templates view to optimize build time
123+
124+
The **Templates** view lists the template instantiations that contributed significantly to build time. Columns provide information about:
125+
126+
The **Time [sec, %]** column shows how long it took to instantiate each template in [wall clock responsibility time (WCTR)](https://devblogs.microsoft.com/cppblog/faster-cpp-builds-simplified-a-new-metric-for-time/#:~:text=Today%2C%20we%E2%80%99d%20like%20to%20teach%20you%20about%20a,your%20build%2C%20even%20in%20the%20presence%20of%20parallelism). This metric distributes the wall clock time among template instantiations based on their use of parallel compiler threads.
127+
128+
The **Specialization Name** column shows the specific template instantiation, including the template arguments that were used. This helps you identify which template specializations are most expensive.
129+
130+
The **Translation Unit** column shows which source file caused this template instantiation. Multiple files can cause the same template instantiation if they include the same header with the template definition.
131+
132+
The **Instantiation File Path** column shows where in your source code the template instantiation happens. This helps you locate the exact line of code responsible for the expensive instantiation.
133+
134+
The view only shows instantiations whose contribution exceeds a certain threshold. If you don't see anything in the **Templates** view, it means the build time isn't dominated by template instantiations.
135+
136+
:::image type="complex" source="./media/templates-view-before-fix.png" alt-text="Screenshot of the Build Insights Templates view showing expensive template instantiations.":::
137+
The Templates view shows two template instantiations of struct S3 taking most (79.4480%) of the build time. The Translation Unit column shows that both LargeValue.cpp and SmallValue.cpp are affected.
138+
:::image-end:::
139+
140+
- Sort by **Time** to find the templates that take the longest to instantiate.
141+
- Expand a template to see its various instantiations and where they happened.
142+
- Use the search box to focus on specific templates.
143+
144+
## Improve build time by optimizing template instantiations
145+
146+
In our example, we can see that two template instantiations of `S3` are taking 83% of the entire build time. The **Translation Unit** column shows that both `SmallValue.cpp` and `LargeValue.cpp` are causing this template instantiation to be included in the build.
147+
148+
Since the **Instantiation File Path** and the **Specialization Name** are the same for both entries, we can derive that there's one expensive template instantiation affecting both of our source files. This explains why the time of each of the two template instantiations are about equal. By including `Templates.h` in both source files, we are causing one template instantiation to add significant time to our build.
149+
150+
From the **Specialization Name** column, we can see that the expensive instantiation is `S3<std::make_index_sequence<1000>>`, which corresponds to this code in `Templates.h`:
151+
152+
```cpp
153+
inline size_t LargeValue()
154+
{
155+
156+
return sizeof(S3<std::make_index_sequence<1000>>);
157+
};
158+
```
159+
160+
There are three main ways to decrease the cost of template instantiations:
161+
162+
### Remove unused templates
163+
164+
Review the template in question and determine if it's being used. If it's not being used, the easiest solution is to remove the function or template. In our example, `LargeValue()` is being used by `LargeValue.cpp`, so we cannot remove it.
165+
166+
You can also consider removing include directives that bring in unnecessary template instantiations. It's easy to forget to remove header files when you're no longer using them, and unused includes can cause significant impact on build time.
167+
168+
### Optimize the template implementation
169+
170+
Look at the template instantiation and determine if there is a way to optimize the code. Some optimization techniques include:
171+
172+
- Reducing the complexity of template metaprogramming
173+
- Using simpler template patterns
174+
- Avoiding recursive template instantiation patterns that lead to exponential growth
175+
- Using `if constexpr` instead of SFINAE where possible
176+
177+
For more advanced template optimization techniques, see [Build Throughput Series: More Efficient Template Metaprogramming](https://devblogs.microsoft.com/cppblog/build-throughput-series-more-efficient-template-metaprogramming/), which provides detailed examples of reducing template instantiation overhead.
178+
179+
### Move template instantiations to source files
124180

125-
The Templates view lists all template instantiations that contributed significantly to build time. Columns include the template name, instantiation time, and the file where the instantiation occurred.
181+
For our purposes, let's assume that we need the template instantiation as-is. We can rely on the third approach: moving the definition that causes the expensive template instantiation to a source file.
126182

127-
- **Sort by Instantiation Time** to find the templates that take the longest to instantiate.
128-
- **Expand a template** to see which code triggered the instantiation and how much time each instance took.
129-
- **Filter templates** using the search box to focus on specific types or functions.
183+
Since `LargeValue.cpp` is the only source file that calls `LargeValue()`, we can move the definition to `LargeValue.cpp`. This prevents the template instantiation from happening in every translation unit that includes `Templates.h`.
130184

131-
If you see that a particular template instantiation dominates build time, consider:
132-
- Refactoring code to reduce the number of instantiations.
133-
- Moving expensive template code out of headers.
134-
- Using explicit instantiation declarations where possible.
185+
To do this, remove the current definition of `LargeValue()` from `Templates.h` and replace it with a declaration:
135186

136-
> **Screenshot suggestion:** Insert a screenshot of the Templates view showing a template instantiation with high build time. **Alt-text:** "Screenshot of the Build Insights Templates view highlighting a template instantiation with high build time."
187+
```cpp
188+
size_t LargeValue();
189+
```
137190

138-
## Interpreting Results
191+
Then, inside `LargeValue.cpp` add the definition:
139192

140-
- If the Templates view is empty, your build is likely not dominated by template instantiations.
141-
- The view only shows templates that take a significant amount of time to instantiate, to avoid clutter and reduce data collection overhead.
142-
- Collecting template instantiation data increases build time. Disable the feature when not actively analyzing templates.
193+
```cpp
194+
size_t LargeValue()
195+
{
196+
return sizeof(S3<std::make_index_sequence<1000>>);
197+
}
198+
```
143199

144-
## Improving Build Times
200+
Now, when you rebuild the project and run Build Insights again, you should see that the expensive template instantiation is no longer listed in the **Templates** view. The build time should also decrease significantly.
201+
202+
:::image type="complex" source="./media/templates-view-after-fix.png" alt-text="Screenshot of the Build Insights Templates view after optimization showing reduced template instantiation time.":::
203+
204+
The Templates view now shows only one instantiation of S3 instead of two, and the total build time has been significantly reduced.
205+
206+
:::image-end:::
207+
208+
The build time has significantly decreased. While the template instantiation of `S3` is still contributing to the build time, we've been able to roughly halve the total time by only including necessary template instantiations. You can see the count of `S3` instantiations is now 1 instead of 2.
209+
210+
This technique scales well to larger projects. If multiple files included `Templates.h`, each of those files would have added the instantiation time of `LargeValue()` to the total build time. By moving the definition of `LargeValue()` to a dedicated source file, we minimize our build time.
211+
212+
## Understanding Templates view results
213+
214+
When interpreting Templates view results, keep these points in mind:
215+
216+
- **Empty view**: If nothing shows up in the Templates view, it means your build time is not dominated by template instantiations. This is actually good news - your templates are not a build bottleneck.
217+
- **Duplicate instantiations**: The same template instantiation appearing multiple times with different translation units indicates that multiple source files are causing the same expensive instantiation. This is often the biggest optimization opportunity.
218+
- **Threshold filtering**: The view only shows instantiations whose contribution exceeds a certain threshold to avoid noise from trivial instantiations.
219+
- **Time aggregation**: The time shown represents the total time spent on that specific template instantiation, including any nested instantiations it may trigger.
145220

146221
For more strategies on improving build times in template-heavy code, see:
147222
- [Templates View for Build Insights in Visual Studio](https://devblogs.microsoft.com/cppblog/templates-view-for-build-insights-in-visual-studio-2/)
@@ -166,8 +241,5 @@ The first article provides an overview of the Templates view and how to use it.
166241
---
167242

168243
**Summary of additional important points from the blog post:**
169-
- The Templates view helps identify which template instantiations are most expensive, making it easier to target optimizations.
170-
- The feature is especially useful for codebases that use heavy metaprogramming or generic libraries.
171244
- The blog post provides more advanced examples, such as using SFINAE and type traits, which can be referenced for deeper dives but are not included in this basic walkthrough.
172-
- The performance impact of enabling Templates view is non-trivial; only enable it when needed.
173-
- The Templates view is designed to be familiar to users of the Functions view, with similar UI and workflow.
245+
-11.2 KB
Loading
65 KB
Loading

0 commit comments

Comments
 (0)