{"id":29790,"date":"2021-11-19T09:41:12","date_gmt":"2021-11-19T09:41:12","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cppblog\/?p=29790"},"modified":"2023-12-06T02:25:04","modified_gmt":"2023-12-06T02:25:04","slug":"cpp-build-throughput-investigation-and-tune-up","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/cpp-build-throughput-investigation-and-tune-up\/","title":{"rendered":"C++ build throughput investigation and tune up"},"content":{"rendered":"<p>Building C++ code is a complex process, launching many build tools in parallel and often running for a long time. It is always desirable to make it faster, but also a challenge to understand what the most effective way would be to achieve this.<\/p>\n<p>We\u2019d like to share some techniques we use to get a &#8220;bigger&#8221; picture of the build, as well as tools that can help to see what is taking time in a particular part of the build. We\u2019ll also talk about MSBuild project options which can improve build parallelism without overwhelming the system, as well as other (not immediately obvious) options which might affect build throughput.<\/p>\n<p>This blog is more like a list of what is currently available, full of instructions and details. Some of the suggestions should be useful for any C++ build, but most of the measurements and tuning options are for MSBuild based projects (vcxproj).<\/p>\n<p>As any performance improvement starts with the measurement, here we are \u2013 measure your build.<\/p>\n<p>Note that the total build time can vary quite noticeably between several identical builds on the same machine \u2013 the system is adjusting to the active processes. So, if you compare builds before and after making some options changes, it is more reliable to run the build several times and get the average. It is also helpful to measure not only the total build time but get more detailed information, so if you get a surprising result, you can figure out why it happened. For MSBuild we recommend running it on the command line and collecting a <a href=\"http:\/\/www.msbuildlog.com\/\">binary log<\/a>.<\/p>\n<h2>Measure your build time using MSBuild Performance Summary<\/h2>\n<p>If your build is MSBuild based, the first thing to do when investigating build performance is to see which projects and which tasks\/targets inside the projects are taking most of the build time. The performance summary data is also very useful for comparing builds using different options.<\/p>\n<p>To get a performance summary for your full build, you can do the following: open a Developer (or MSBuild) Command Prompt and run the build of your solution with the following options (replace Configuration and Platform values with the ones your solution actually has):<\/p>\n<pre class=\"prettyprint\">msbuild \/m \/t:clean \/p:Configuration=\"Debug\";Platform=\"x86\" YourSolution.sln \r\nmsbuild  \/m \/fl  -flp:PerformanceSummary;v=q;LogFile=Perf.log \/p:Configuration=\"Debug\";Platform=\"x86\" YourSolution.sln\r\n<\/pre>\n<p>The &#8220;quet&#8221; or &#8220;minimal&#8221; verbosity setting (<code>-flp:PerformanceSummary;v=q<\/code>) is recommended as console logging itself takes noticeable time. But you can set the verbosity to other levels if you want more build info in the Perf.log. You can also add <code>\/detailedSummary<\/code> to see msbuild.exe <a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/msbuild-4-detailed-build-summary\/#gimme-some-numbers\">nodes utilization<\/a>).<\/p>\n<p>The same information can be extracted from a binary log. We recommend creating binary logs when investigating your builds. To create a binary log, run:<\/p>\n<pre><code class=\"language-txt\">msbuild \/m \/t:clean \/p:Configuration=\"Debug\";Platform=\"x86\" YourSolution.sln \r\nmsbuild \/m \/bl:build.binlog \/p:Configuration=\"Debug\";Platform=\"x86\" YourSolution.sln<\/code><\/pre>\n<p>To extract the perf info into Perf.log, run:<\/p>\n<pre><code class=\"language-txt\">msbuild -noconlog -flp:PerformanceSummary -flp:v=q  build.binlog\r\nren msbuild.log Perf.log<\/code><\/pre>\n<p>You can also enable &#8220;Build Timings&#8221; for VC projects in the IDE by setting &#8220;Tools\/Options\/Projects and Solutions\/VC++ Project Settings\/Build Timings&#8221; = &#8220;Yes&#8221;. This will create the Perf Summary for each project, but not for the whole solution build. Thus, using the command line is better to see the &#8220;whole picture&#8221;.<\/p>\n<p>In the Perf.log you\u2019ll find times (in ms) it took to build the whole solution, each project (in the time increasing order) and commutative time of all targets and tasks (also in the time increasing order). Note that project build time and some targets (like ResolveProjectReferences target) include the wait for referenced projects to be built. You can use the Timeline tab of the binlog viewer to see if other projects were built as a part of a particular project build.<\/p>\n<p>For a solution containing mostly C++ projects, cl and link would usually be the tasks taking most of the time:<\/p>\n<pre><code class=\"language-txt\">Project Performance Summary:\r\n\u2026\r\n    1100252 ms  d:testMySolution.sln          1 calls \uf0df solution build time (msbuild \/m)\r\n\r\nTask Performance Summary:\r\n\u2026\r\n     22495731 ms  Link    250 calls \r\n    152500624 ms  CL      250 calls <\/code><\/pre>\n<p>The task time is the sum of all times the task was executing for all projects and thus it can be bigger than the total build time. For CL and Link tasks their time is very close to the cl.exe and link.exe time.<\/p>\n<h2>Use Build Insights to see the build timeline for cl.exe and link.exe<\/h2>\n<p>Most of the C++ builds time is usually spent in the compiler. To visualize what is going on during the build, see the processes running in parallel and pivot on the parts that take most of the time, you can use the <a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/introducing-c-build-insights\/\">Build Insights<\/a> tool.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2019\/11\/word-image.gif\"><img decoding=\"async\" class=\"alignnone wp-image-25179 size-full\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2019\/11\/word-image.gif\" alt=\"\" width=\"881\" height=\"680\" \/><\/a><\/p>\n<h2>Change options to improve C++ build throughput<\/h2>\n<p>There are many parameters which can affect build throughput and different codebases can benefit from different sets of options. Here we&#8217;ll talk about antivirus and project settings which are easy to change and which can potentially greatly improve your build throughput.<\/p>\n<h3>1. Check your antivirus settings<\/h3>\n<p>C++ builds produce a lot of intermediate files and we often see the file system as a bottleneck there. With your antivirus scanning all build outputs, the problem is greatly amplified.<\/p>\n<p>Windows Defender Antivirus automatically excludes most of the common build tools when they are found in the default install locations. But if you install Visual Studio in a custom location or use many additional build tools, your build throughput might be affected.<\/p>\n<p>To see if Windows Defender scans are impacting your build, you can use <a href=\"https:\/\/techcommunity.microsoft.com\/t5\/microsoft-defender-for-endpoint\/announcing-performance-analyzer-for-microsoft-defender-antivirus\/ba-p\/2713911\">Performance Analyzer for Microsoft Defender Antivirus<\/a>. The tool collects minimal data so you can run it for a good chunk of your build (10-20 min is usually enough) if not the whole build. We recommend closing all application unrelated to the build before collecting the data to avoid seeing unrelated to build processes in the report.<\/p>\n<p>To collect the data and see the affected build processes:<\/p>\n<ul>\n<li>Open a Windows PowerShell and run:\n<pre><code class=\"language-txt\">New-MpPerformanceRecording -RecordTo MyBuild.etl<\/code><\/pre>\n<\/li>\n<li>Rebuild your code in the IDE or on the command line<\/li>\n<li>After the build is finished (or after 10-20 min) go back to the PowerShell and stop the recording by hitting any key<\/li>\n<li>In PowerShell run\n<pre><code class=\"language-txt\">Get-MpPerformanceReport -TopProcesses:20 MyBuild.etl<\/code><\/pre>\n<p>This will give you the list of the affected processes, similar to the following one:<\/p>\n<pre><code class=\"language-txt\">TopProcesses\r\n============\r\n\r\nCount TotalDuration MinDuration AverageDuration MaxDuration MedianDuration ProcessPath\r\n----- ------------- ----------- --------------- ----------- -------------- -----------\r\n8193  62272.1020ms    0.1790ms        7.6006ms  119.5682ms       6.8465ms   D:Visual Studio 17VCToolsMSVC14.30.30528binHostx64x86cl.exe\r\n1068  14587.9547ms    3.2531ms       13.6591ms 927.2716ms       6.0416ms    D:Visual Studio 17VCToolsMSVC14.30.30528binHostx64x86link.exe\r\n\u2026<\/code><\/pre>\n<p>You can add the build tools from the trusted locations to the excluded files or directories list in the <a href=\"https:\/\/docs.microsoft.com\/microsoft-365\/security\/defender-endpoint\/configure-extension-file-exclusions-microsoft-defender-antivirus?view=o365-worldwide#exclusion-lists\">Windows Defender settings.<\/a><\/li>\n<\/ul>\n<h3>2. Redefine TMP directory.<\/h3>\n<p>During compilation, cl.exe creates a tmp file per each source in the TMP folder. When many cl.exe processes are running in parallel and simultaneously creating a lot of files in the same folder it creates a lot of stress for the file system.<\/p>\n<p>Using different TMP folders for different projects (and preferably not on the system drive) often makes the build faster, especially on powerful machines with many CPUs where disk I\/O and file system are more often a bottleneck.<\/p>\n<p>We are planning to address this problem in the future VS releases, but meanwhile you can redefine the TMP environment variable to be different for different projects. See the proposed <code>Directory.Build.props<\/code> sample at the end of the blog.<\/p>\n<h3>3. Tune build options for better parallelism.<\/h3>\n<p>Many C++ build operations support parallel execution. A general assumption is that the build should be faster when more build operations are running in parallel. This is true, but only to a point when the build is not overwhelming the system capacity to distribute machine resources between processes and threads.<\/p>\n<p>Most of the build tools are heavy users of CPU, memory, and the file system. Depending on the number of source files, their size, and content, any of these components can be a bottleneck preventing the build from being faster when more tools are running in parallel. When a resource limit is hit, running more build operations in parallel will make the build slower, rather than faster, sometimes significantly. For instance, the <code>msbuild \/m<\/code> + <code>cl \/MP<\/code>\u00a0resource overuse problem has been known for quite some time, but recently became more frequent as more and more computers have 32+ logical CPUs.\nThe problem of optimal build parallelism is quite complex as it is hard to predict up front the resource usage of a particular build operation and pretty much impossible to predict actual resource availability for the whole time of that build operation. But some heuristics can be used, at least for the number of running processes and threads.<\/p>\n<h4><em>MSBuild Resource Manager<\/em><\/h4>\n<p>In VS 2019 16.10, MSBuild introduced <a href=\"https:\/\/github.com\/dotnet\/msbuild\/blob\/main\/documentation\/specs\/resource-management.md\">cross-process resource management<\/a>, which allows build parts (tasks) of different projects communicating their anticipated CPU usage and limiting this usage if resources are already reserved by other build parts. All C++ build tasks that launch several processes (like cl.exe or custom build tools) or the ones that are known to use many threads (like link.exe) participate in this communication.<\/p>\n<p>The MSBuild Resource Manager support in VC projects is available in VS 2019 16.11 and later. In VS 2022 17.0 it was turned on by default, but we found that this negatively impacts build throughput in some codebases, so in 17.2 we turned it off to avoid this. To activate it the following property should be defined as an environment variable or as an MSBuild property for all projects (see Directory.Build.props sample):<\/p>\n<p><code>set UseMSBuildResourceManager=true<\/code><\/p>\n<p>If you don\u2019t use <code>\/MP<\/code> for your build currently, turn it on and give it a try. To affect all projects, define the following property as an environment variable or as an MSBuild property for all projects (see Directory.Build.props sample):<\/p>\n<p><code>set CL_MP = true<\/code><\/p>\n<p>By default, the MSBuild Resource Manager will allow maximum 2*(number of CPU cores) to be used simultaneously by all project\u2019s tasks. The 2x cores (instead of just 1x) limit is partially dictated by the current MSBuild scheduler architecture, but also seems to allow better build throughput on average. Most of the time the build will use less than 2xCPUs and when it does, the system usually tolerates 2x CPU oversubscription quite well unless bottlenecks other than the CPU are hit by the build (see Many Cores Machines section).<\/p>\n<p>There are also a couple of &#8220;knobs&#8221; to try if the default behavior is not good enough.\nIn addition to setting the maximum number of projects allowed to be built in parallel (<code>msbuild \/m:nProjects<\/code>), you can set the following environment variables (cannot be MSBuild properties) to modify the behavior:<\/p>\n<ul>\n<li><code>MSBUILDCORELIMIT=N<\/code> where N is the max number of cores to be given to one project. By default it\u2019s the number of logical CPUs on the machine<\/li>\n<li><code>MSBUILDNODECOREALLOCATIONWEIGHT= [0 \u2013 100]<\/code>\n0% means that MSBuild nodes don\u2019t consider using CPUs and 100% means that each MSBuild node would be considered using 1 CPU. In C++ builds, MSBuild processes CPU usage is small comparing to the compiler CPU usage, so 0 should be OK. But for mixed C# and C++ solutions it probably should be set to something between 50 and 100.<\/li>\n<\/ul>\n<p>If for some reason building with the MSBuild Resource Manager is slower for your build and you don\u2019t want to experiment with other options, you can disable it by setting <code>UseMSBuildResourceManager<\/code> as false.<\/p>\n<h4><em>MultiToolTask (MTT)<\/em><\/h4>\n<p>Other options which can be used to limit the number of cl.exe processes running in parallel are described in <a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/improved-parallelism-in-msbuild\/\">Improve Parallelism in MSBuild<\/a>.<\/p>\n<p>To activate MTT mode set the following properties as environment variables or as MSBuild properties for all projects (see also the <code>Directory.Build.props<\/code> sample below):<\/p>\n<pre><code class=\"language-txt\">set UseMultiToolTask=true\r\nset EnforceProcessCountAcrossBuilds=true<\/code><\/pre>\n<p>This will make the build launch a separate cl.exe process for each C\/C++ source and limit the number of simultaneously running cl processes (across all project builds) to <code>CL_MPCOUNT<\/code>, which is by default set to the number of logical processors.<\/p>\n<p>MultiToolTask mode can be also used together with the MSBuild Resource Manager. This might be beneficial for some builds as instead of asking the MSBuild Resource Manager for available resources only once before launching the top-level <code>cl.exe \/MP<\/code>, the build will ask it before launching cl.exe for each source file.<\/p>\n<p>Note, that for projects with many small and simple C\/C++ files (i.e., when individual file compilation is not taking a long time), launching a separate cl.exe processes for each file would bring a noticeable overhead. So, this option is recommended to use when most of the source files are relatively large and complex.<\/p>\n<p>In VS 2022, the new experimental &#8220;ClServer&#8221; mode has been added to address the process creation overhead in MTT mode by using server-client model similar to <code>cl.exe \/MP<\/code>. The server would spawn worker cl.exe processes, then dispatch work via IPC. The server resides in MSBuild process so is in-sync with the resource manager while scheduling work dynamically\u2014allocating more workers or freeing resources to scaling down to deal with &#8220;long pole&#8221; compiles.<\/p>\n<p>To enable this mode the following property should be defined as an environment variable or as an MSBuild property for all projects (see Directory.Build.props sample below):<\/p>\n<p><code>set EnableClServerMode=true<\/code><\/p>\n<h4><em>Increase build parallelism for native C++ projects (experimental)<\/em><\/h4>\n<p>This option is experimental and works only for command line builds currently (not supported for the IDE build).<\/p>\n<p>By default, if project B is referencing project A, the build of project B will not start until project A\u2019s build is finished.\nThis makes sense for managed projects where assemblies must exist before they can be used as references in the compilation.<\/p>\n<p>But native C++ code compilation usually does not use any build outputs from the referenced projects, only the linker does.\nEven with C++20 modules, where compilation does use the build outputs (modules) from the referenced projects, it only needs to wait for the referenced project compilation step to finish but does not need to wait for the link to be complete.<\/p>\n<p>To allow the compilation step of the referencing projects to start as soon as the compilation step of the referenced projects is finished:<\/p>\n<p><code>set BuildPassReferences=true<\/code><\/p>\n<p>As these options would allow more build parts running simultaneously, make sure to enable the MSBuild Resource Manager and\/or MultiToolTask with <code>EnforceProcessCountAcrossBuilds<\/code>.<\/p>\n<p>The command line should look like:<\/p>\n<p><code>msbuild \/p:Configuration=Debug;Platform= x64 \/t:BuildGenerateSources;BuildCompile;BuildLink solution.sln<\/code><\/p>\n<p>How it works:<\/p>\n<p>By default, MSBuild starts project build execution after all projects it references finish building.\nEach VC project build consists of BuildGenerateSources, BuildCompile and BuildLink targets executed one after another. They are historically called &#8220;build passes&#8221;.<\/p>\n<p>The default build timeline for two projects where ProjectB is referencing ProjectA looks like<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2021\/11\/Build.png\" alt=\"Regular build\" \/><\/p>\n<p>When <code>BuildPassReferences<\/code> is set to true, a project B\u2019s <code>BuildGenerateSources<\/code> target will be executed as soon as project A\u2019s <code>BuildGenerateSources<\/code> target finish building. The project B\u2019s <code>BuildCompile<\/code> target will wait for project B\u2019s <code>BuildGenerateSources<\/code> target to finish executing, as well as project A\u2019s <code>BuildCompile<\/code> targets. Similarly, a project B\u2019s <code>BuildLink<\/code> target will wait for project B\u2019s <code>BuildCompile<\/code> target and project A\u2019s <code>BuildLink<\/code> target.<\/p>\n<p>So, with <code>BuildPassReferences = true<\/code>, the build timeline would look like<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2021\/11\/BuildPasses.png\" alt=\"Build with pass references\" \/><\/p>\n<h3>4. Tune sources, includes and precompiled headers (PCH)<\/h3>\n<p>To see which sources are taking most of the compiler time, use <a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/introducing-c-build-insights\/\">Build Insights<\/a>. This tool will help you to see if adding a particular include to the pch would save a lot of compilation time. It will also allow you to view the build timeline.<\/p>\n<p>Check the following blog post for adjusting PCH files:\n<a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/precompiled-header-pch-issues-and-recommendations\/\">Precompiled Header (PCH) issues and recommendations<\/a><\/p>\n<p>If your files are well isolated, you can also try using Unity(Jumbo) builds:\n<a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/support-for-unity-jumbo-files-in-visual-studio-2017-15-8-experimental\/\">Support for Unity (Jumbo) Files in Visual Studio 2017 15.8 (Experimental)<\/a><\/p>\n<h3>5. Special considerations for machines with 64+ CPUs<\/h3>\n<p>The following recommendations are based on the build time measurements performed on a 192 cores Windows Server machine.<\/p>\n<ul>\n<li>If you are running Windows Server 2016 on such a machine, it is highly recommended to upgrade it to WS2019. WS2016 was not optimized for launching many (64+) instances of the same exe, which resulted in poor performance of 64+ cl.exe running together.<\/li>\n<li>When using Windows Server 2019, make sure that antivirus check is not affecting your build and TMP directory is redefined (i.e. follow recommendations #1 and #2 of this blog, see the chart below).<\/li>\n<li>The build is likely to hit file system and disk I\/O bottleneck when running a lot of build tools in parallel. If you\u2019ve adjusted your build options for the best parallelism (#3), but still see low CPU utilization during build, it is likely that build is hitting a bottleneck other than CPU. Try limiting the number of projects running in parallel, as well as setting <code>MSBUILDCORELIMIT<\/code> to a lower number &#8211; this might actually improve your build throughput.<\/li>\n<\/ul>\n<p>In one of our tests, we\u2019ve built a generated solution containing 250 projects, 250 cpp files each, with no project references. The C++ code was also generated and, admittedly, quite simple, containing one class per file, up to 30 methods each.<\/p>\n<p>The following chart shows build times of this solution with different system and TMP options.\nEach bar corresponds to the <code>msbuild \/m:[nProjects]<\/code>\u00a0build time, no other options were set. As the test projects did not have any project references, that was enough to achieve best parallelism.\nEach series contains build times when number of projects built in parallel (and thus max number of cl.exe instances running together) was 10, 20, 30, 40, 60, 80, 100, 120, 140, 160, and 180.<\/p>\n<p>The system\/TMP setting for each series are:<\/p>\n<ol>\n<li>WS2016 Default settings<\/li>\n<li>WS2019 Default settings, custom VS install location (Defender on, no exclusions, default TMP folder <code>c:users[username]AppDataLocalTemp<\/code>)<\/li>\n<li>WS2019* Build tools are excluded from the Defender scan. Default TMP folder, not excluded from Defender scan.<\/li>\n<li>WS2019** Build tools and default TMP folder are excluded from the Defender scan<\/li>\n<li>WS2019*** Build tools are excluded from the Defender scan, TMP is set to project specific location, different for each project.<\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2021\/11\/Chart.png\" alt=\"Build time (ms)\" \/><\/p>\n<p>Note that in all series, build time did not improve much (and even got worse) when building more projects in parallel after some point. For this particular solution, building just ~40 projects in parallel showed the best results.<\/p>\n<p>We\u2019ve also tested other generated solutions with different number of projects, longer code, project references, etc. We also used different build options, especially the ones we recommend using in section#3.\nThe trends were quite similar, though the optimal number of parallel processes might differ.<\/p>\n<p>The &#8220;real&#8221; code compilation usually takes much longer than the compilation of our small and simple generated files, so File System bottleneck might be not so pronounced there. But changing the antivirus and TMP settings improved the build times there as well, though not as much.<\/p>\n<h2>Directory.Build.props sample to set options for all projects<\/h2>\n<p>Create<code> Directory.Build.props<\/code> in the root directory to affect all projects under this root.\nThis is a sample content of<code> Directory.Build.props<\/code> you can use to try different build settings.<\/p>\n<pre><code class=\"language-xml\">&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\r\n&lt;Project&gt;\r\n  &lt;PropertyGroup&gt;\r\n    &lt;!-- To enable project specific directory for temporary files. --&gt;\r\n    &lt;UseProjectTMPDirectory&gt;true&lt;\/UseProjectTMPDirectory&gt;\r\n\r\n    &lt;!-- To enable MSBuild Resource Manager in VS 2019 16.11 (on by default in VS 2022) --&gt;\r\n    &lt;UseMSBuildResourceManager&gt;true&lt;\/UseMSBuildResourceManager&gt;\r\n\r\n    &lt;!-- Uncomment to enable MultiToolTask (MTT) mode. --&gt;\r\n    &lt;!--&lt;UseMultiToolTask&gt;true&lt;\/UseMultiToolTask&gt;\r\n      &lt;EnforceProcessCountAcrossBuilds&gt;true&lt;\/EnforceProcessCountAcrossBuilds&gt;--&gt;\r\n\r\n    &lt;!-- Uncomment to enable experimental MTT ClServer mode, available in VS 2022. --&gt;\r\n    &lt;!--&lt;EnableClServerMode&gt;true&lt;\/EnableClServerMode&gt;--&gt;\r\n\r\n    &lt;!-- Uncomment and change the value to control the maximum number of cl.exe processes running in parallel. \r\n         If using MTT without MSBuild Resource Manager, 10-20% oversubscription is often beneficial. --&gt;\r\n    &lt;!--&lt;CL_MPCount&gt;20&lt;\/CL_MPCount&gt;--&gt;\r\n\r\n    &lt;!--Uncomment to allow executing more build operations in parallel--&gt;\r\n    &lt;!--&lt;BuildPassReferences&gt;true&lt;\/BuildPassReferences&gt; --&gt;\r\n  &lt;\/PropertyGroup&gt;\r\n\r\n  &lt;ItemDefinitionGroup&gt;\r\n    &lt;!--  Enable parallel compilation (cl.exe \/MP) --&gt;\r\n    &lt;ClCompile&gt;\r\n      &lt;MultiProcessorCompilation&gt;true&lt;\/MultiProcessorCompilation&gt;\r\n    &lt;\/ClCompile&gt;\r\n    &lt;!--  Enable parallel execution of a custom build tool--&gt;\r\n    &lt;CustomBuild&gt;\r\n      &lt;BuildInParallel&gt;true&lt;\/BuildInParallel&gt;\r\n    &lt;\/CustomBuild&gt;\r\n  &lt;\/ItemDefinitionGroup&gt;\r\n\r\n  &lt;!-- Define project specific directory for temporary cl.exe files --&gt;\r\n  &lt;Target Name=\"SetProjectTMPDirectory\"\r\n        BeforeTargets=\"BeforeClCompile\"\r\n        Condition=\"'$(DesignTimeBuild)' != 'true' and '$(UseProjectTMPDirectory)' == 'true'\"&gt;\r\n    &lt;PropertyGroup&gt;\r\n      &lt;OriginalTmp&gt;$(TMP)&lt;\/OriginalTmp&gt;\r\n    &lt;\/PropertyGroup&gt;\r\n    &lt;MakeDir Directories=\"$(IntDirFullPath)TMP\"\/&gt;\r\n    &lt;SetEnv Name =\"TMP\"\r\n            Value =\"$(IntDirFullPath)TMP\"\r\n            Prefix =\"false\"&gt;\r\n    &lt;\/SetEnv&gt;\r\n  &lt;\/Target&gt;\r\n\r\n  &lt;!-- Restore TMP directory for other tools to avoid incremental build problems --&gt;\r\n  &lt;Target Name=\"RestoreTMPDirectory\"\r\n          BeforeTargets=\"AfterClCompile\"\r\n          Condition=\"'$(DesignTimeBuild)' != 'true' and '$(UseProjectTMPDirectory)' == 'true'\" &gt;\r\n    &lt;SetEnv Name =\"TMP\"\r\n            Value =\"$(OriginalTmp)\"\r\n            Prefix =\"false\"&gt;\r\n    &lt;\/SetEnv&gt;\r\n  &lt;\/Target&gt;\r\n&lt;\/Project&gt;<\/code><\/pre>\n<h2>Send Us Feedback<\/h2>\n<p>Build is a complex process, and its performance depends on many factors and circumstances. Building different codebases on different hardware would benefit from different build settings. We hope you can try some of the options described in the blog and see if they improve your build time.<\/p>\n<p>If you try any suggestions, please let us know, we love to hear from you! You can leave your comments below or email us at <a href=\"mailto:visualcpp@microsoft.com\">visualcpp@microsoft.com<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Building C++ code is a complex process, launching many build tools in parallel and often running for a long time. It is always desirable to make it faster, but also a challenge to understand what the most effective way would be to achieve this. We\u2019d like to share some techniques we use to get a [&hellip;]<\/p>\n","protected":false},"author":4347,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-29790","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus"],"acf":[],"blog_post_summary":"<p>Building C++ code is a complex process, launching many build tools in parallel and often running for a long time. It is always desirable to make it faster, but also a challenge to understand what the most effective way would be to achieve this. We\u2019d like to share some techniques we use to get a [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/29790","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/4347"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=29790"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/29790\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=29790"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=29790"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=29790"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}