Speed-up VC++ builds

The larger a VC++ project is (or any project for that matter) the more time it takes to build. If you have solutions with many large projects the build times could get into your way. Starting a rebuild and going to lunch was a common scenario for me, as building took 20-25 minutes. Of course, you don’t rebuild everything all the time, but sometimes is enough to change something in a header somewhere deep inside the dependency web and trigger a rebuild of many or all the projects in a solution.

Using compiler switches and other tricks I managed to reduce the build time with about 50% or more (the percent of speedup is similar on different machines, regardless of the previous build times on those machines). Replacing the hard disk with an SSD provided an additional 25% speed. My full build times have decreased from 20-25 minutes to about 7 minutes.

First off all, Visual Studio enables parallel projects builds by default. As long as your projects don’t have dependency and can be built in parallel, it is possible to have up to 32 projects built at the same time. By default the number of projects built in parallel is set to the number of available cores. This option can be change from Tools > Options > Projects and Solutions > Build and Run.

vcbuild1

The VC++ compiler also supports multi-processor compilation. This can be enabled with a compiler switch, /MP. The result of this switch is that the compiler spawns into additional processes that simultaneous compile the source files. This option can be set per project from Project > Properties > Configuration Properties > C/C++ > General.

vcbuild2

This option is however incompatible with several compiler and language features. In case of incompatibility the behavior differs:

  • if the incompatibility is with another compiler option a warning is displayed and the /MP options is ignored
  • if the incompatibility is with a language feature an error is issued and compilation stops or continues depending on the error level

The incompatible features are: #import processor directive, /GM (enables incremental build), /Yc (writes a precompiled header file), /E and /EP (copies pre-processor output to the standard console), /showIncludes (writes a list of include files to the standard error console). These features are incompatible with /MP because they would imply shared resources (console or file) to be used possible at the same time from different processes.

The workaround for the #import processor directive is to move the directives to a file that is not built with the /MP option. However, in practice I had problems with that and the workaround that actually worked was to move the #import directives to the pre-compiled header. That is built (the corresponding source file actually) synchronously before the compilation of any other translation unit starts, so there are no incompatibilities. However, this has the drawback that any change in the imported type library will trigger a rebuild of the precompiled header and of the whole project.

vcbuild3

Below is a table of full build times for various VC++ projects from the same solution. The values were reported by MSBuild. The actual time values (shown to hundredths of a second) are not important (as they vary across builds and machines). What is important is the speed-up before enabling /MP and after it.

Before After
Release Debug Release Debug
00:00:58.43 00:00:53.14 00:00:37.32 00:00:25.23
00:00:45.41 00:00:33.25 00:00:12.16 00:00:07.47
00:00:56.85 00:00:54.90 00:00:51.35 00:00:50.72
00:00:45.41 00:00:44.34 00:00:24.41 00:00:20.16
00:01:00.92 00:01:05.97 00:01:15.40 00:01:14.07
00:04:17.89 00:04:25.88 00:01:34.66 00:01:17.97
00:02:59.41 00:02:26.42 00:01:11.99 00:00:54.07
00:00:46.96 00:00:43.96 00:00:17.70 00:00:17.41
00:00:46.05 00:00:46.05 00:00:16.69 00:00:14.40
00:01:44.84 00:01:35.11 00:00:30.29 00:00:28.13
00:00:11.02 00:00:14.26 00:00:07.97 00:00:08.24
00:00:09.28 00:00:12.75 00:00:07.59 00:00:07.59
00:00:08.46 00:00:08.95 00:00:10.89 00:00:08.25
00:00:18.68 00:00:19.79 00:00:14.32 00:00:11.35
00:02:46.37 00:00:50.76 00:01:52.16 00:00:28.88
00:00:13.87 00:00:11.66 00:00:09.24 00:00:11.06
00:01:05.37 00:00:54.76 00:00:25.45 00:00:26.83
00:00:29.00 00:00:16.68 00:00:13.32 00:00:12.94
00:00:25.79 00:00:14.05 00:00:12.09 00:00:12.04
00:00:22.80 00:00:11.50 00:00:11.60 00:00:11.93
00:00:31.76 00:00:39.33 00:00:25.00 00:00:21.19
00:00:56.01 00:00:59.04 00:00:26.62 00:00:23.95
00:00:20.40 00:00:12.92 00:00:08.64 00:00:07.99
00:00:16.48 00:00:18.61 00:00:09.18 00:00:08.71
00:00:09.74 00:00:10.49 00:00:06.84 00:00:09.84

Another strategy for increasing the build times is to reduce the number of times framework headers (STL, MFC, ATL, etc.) or headers from your project that do not change often and are included in many places are included into the various source files of your projects. These headers can be put in the pre-compilead header, and therefore compiled just once.

The next table shows the additional speed-up gain for several projects after moving framework headers to the pre-compiled header of each project.

Before After
Release Debug Release Debug
00:00:37.32 00:00:25.23 00:00:32.79 00:00:19.24
00:00:12.16 00:00:07.47 00:00:04.90 00:00:02.41
00:00:51.35 00:00:50.72 00:00:44.15 00:00:37.25
00:00:24.41 00:00:20.16 00:00:20.19 00:00:20.16
00:01:15.40 00:01:14.07 00:01:14.10 00:01:10.56
00:01:34.66 00:01:17.97 00:01:23.60 00:01:22.15
00:01:11.99 00:00:54.07 00:01:11.70 00:00:43.20

The speed-up gain by using these techniques may vary depending on your project specifics. In some cases the gain may not be significant or the build time may actually increase. You should play around with these settings and enable them only when they help you.

In summary, some of the strategies that can help increase your build times are:

  • break dependencies between projects they can be built in parallel
  • if you have large projects try to break them in smaller, independent projects; the more such projects you have the more work can be done in parallel
  • use multi-processor compilation (/MP) for C++ projects to enable compiling multiple translation units at the same time
  • move framework headers (STL, MFC, ATL, etc.) and other headers that do not change and are included all over your project to the pre-compiled header
  • use a SSD and keep your sources on it
, , , , , Hits for this post: 27338 .

Text templates (aka T4) is a great feature in Visual Studio, that proves helpful in many scenarios. I use it for instance in developing Alchemy. However, it has a significant drawback: it does not generate code automatically when you build your solution. To build the files and generate their output you have to manually run either Run Custom Tool command for each .tt file, or Transform All Templates for the entire solution.

Run Custom Tool

Transform All Templates

The good news is that Visual Studio 2010 has added capabilities for building the text templates files automatically at the build time. Basically, what you have to do is two things: first install the Visual Studio Visualization and Modeling SDK. Second, manually add the following to the project file:

And that should do the trick. When you build the project, the .tt files will also be built.

To read more about this topic see:

, , , , Hits for this post: 48323 .

Yesterday I have installed Visual Studio 2010 and decided to try my VSBuildStatusAddin. It work on the first try, only with a change to the .AddIn configuration file.

Here is some screen shots in Visual Studio 2010.

VSStatusBuild in Visual Studio 2010

VSStatusBuild in Visual Studio 2010

Visual Studio 2010 about window with VSbuildStatus addin

Visual Studio 2010 about window with VSbuildStatus addin

The images above show a new version of the add-in, 1.1.0. This new version provides the following features:

  • displays the build/clean/deploy progress on a status bar
  • shows information about latest available version with link to download page
  • as already explained, works in Visual Studio 2010

The new version is available at the Visual Studio Gallery.

, , , , Hits for this post: 44272 .

I have fixed several bugs on version 1.0.4 of my VSBuildStatus add-in for Visual Studio that displays the status of a build/clean/deploy operation. The bugs were mainly about the batch builds. The new version is 1.0.5.

You can download this Visual Studio 2005 & 2008 add-in from here. If you are using a previous build I encourage you download and use the latest.

, , , , Hits for this post: 38078 .