6

Most of programmers who are involved into development of more or less large project(s) know how annoying the process of compilation can be. There are some other things which are dependent on compilation, for example unit tests. TDD requires tests to execute fast, otherwise developers tend to run them rarely.

The process of compilation of whole solution my team is working with takes about 5 minutes. Our Visual Studio solution consists of many projects, so we usually don't have to recompile all of them. Normally, this 'partial' compilation requires about 2 minutes. It's easy to calculate that compiling the solution 10 times we lose 20+ minutes! The situation is even worse when we have to rebuild whole solution often. For this reason I unload a lot of projects manually very often but it scarcely helps.

1. How can we accelerate the process of compilation?

2. Can you recommend any Visual Studio [2010] extension which allows continuous background solution compilation?

4
  • which language?
    – gbjbaanb
    Feb 16, 2012 at 23:11
  • Well, now C# only... and may be Nemerle and/or F# in far future. Feb 16, 2012 at 23:14
  • 1
    ok, see my answer for the link to the MSDN team development guide "Chapter 3 – Structuring Projects and Solutions in Source Control"
    – gbjbaanb
    Feb 16, 2012 at 23:26
  • 4
    I'm voting to close this question as off-topic because it is about a tooling implementation. It would be better asked on StackOverflow but is too old to migrate.
    – user53019
    Jan 31, 2015 at 16:19

6 Answers 6

4

The most effective technique that I know of is to build referenced projects into compiled assemblies, so that you're only compiling the project you're currently working on, and not a dozen others.

Yes, you do lose access to the source code for those assemblies, but presumably they're not changing every five minutes, and presumably someone else is working on that code, not you. When a new revision for that assembly gets released, you can simply copy it over to your project/solution.

3
  • Thank you very much for a fast reply! To be honest, I think that this approach won't make a big difference in time of compilation. When csc.exe (C# compiler) builds the solution, it checks each project for modifications. Projects that were modified and that refer to other modified projects are compiled then. This checking is a cheap operation. Anyway, I will try what you said, because theory and practice may differ. Feb 16, 2012 at 22:09
  • When csc.exe (C# compiler) builds the solution, it checks each project for modifications. -- That's because you're still compiling the source. What I propose is to eliminate the source code for those projects from your solutin by compiling them to DLL's, and then referencing those DLL's in your project. Feb 16, 2012 at 22:20
  • Well, I believe we have already done that in our solution. It consists of 40+ small projects which are almost independent. Less than 10 projects are widely used and rarely modified (e.g. Conrols.WinForms.dll, Controls.Wpf.dll, GlobalTypes.dll and so on.) Feb 16, 2012 at 22:30
5

Use the "unload project" feature to unload projects that you aren't ready to remove from the solution, but don't want to run/compile them everytime you need to debug or if you want to periodically click "compile solution" without hitting the slow project.

If you are using a distributed version control, you might want to check your code into your local repo frequently & then have a personal build server pull & compile code throughout the day. Then when your entire solution compiles, push your repo to the team's central repo. Or you could occasionally xcopy your code to a separate machine with a build server that doesn't pull from a repo. In both cases, this assumes you have a spare machine and a build server (TeamCity is a good one & has a free version)

6
  • 1
    As I wrote, I actually use project unloading time to time... Our project isn't so huge to compile it separately from VS. The question is how to decrease the compilation time on the local machine. Feb 16, 2012 at 22:11
  • 2
    Beg for solid state disks, or if you can take a bit more risk to avoid swapping drives, use a RAM disk. C# is disk bound with respect to compilation performance. Feb 16, 2012 at 22:14
  • 1
    Thank you for an excellent advice. I and my teammates have already discussed this variant but I forgot it. I was not sure about SSD, but now I think that we have to try it. Feb 16, 2012 at 22:20
  • I would be cautious with SSD's. When they fail, they fail without warning, generally taking all your data with them. Feb 16, 2012 at 22:33
  • 1
    @RobertHarvey They are bad like that, however I would think that most projects would utilise version repositories these days, plus something like SharePoint, cloud storage or even just a network drive for Project Documentation & related materials. Plus he doesn't need to "change out" his hard drive if he's using a desktop, he can just put in a new SSD, and just move the source directory to that disk- again he wouldn't lose 'all' his data.
    – Robotnik
    Feb 16, 2012 at 23:16
4

I use a ramdisk (40 MB) to speed up compilations. Before starting Visual Studio, I launch a PowerShell script that replaces the bin/ and obj/ directories with junctions to the ramdisk.

param([Parameter(Mandatory=$true)][string] $folder)

function MoveToRamdisk($folder, $target){
    $folder.Delete($true);
    [IO.Directory]::CreateDirectory($target);
    cmd /c mklink /J $folder.FullName $target
}

function MoveRepositoryFolderToRamdisk($folder){
    $target = $folder.FullName.Replace('D:\Repositories\', 'E:\TempBinaries\');
    MoveToRamdisk $folder $target
}

dir $folder -Recurse -Include bin,obj | %{ MoveRepositoryFolderToRamdisk $_ }

MoveToRamdisk (Get-Item "${env:LocalAppData}\Microsoft\VisualStudio\10.0\ProjectAssemblies") 'E:\VsProjectAssemblies'

Then create a link to:

%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe "C:\Path\To\InitializeDevelopmentRamDisk.ps1" "D:\Repositories\Solution1"

I use DataRAM RamDisk, it's freeware and does not run background processes.

1
  • just a note, but the folder names are case sensitive in the above example, so if these don't match the names of the folders on your disk, nothing is replaced. Good solution though. I ended up doing a ToLower on the $folder.FullName and matching on a lowercase name to minimise the chances if I change the hardcoded name again.
    – Sam Holder
    May 22, 2012 at 17:29
3

One of the best ways that I've found to increase compile time is to not do the compile in visual studio and instead use msbuild. Using msbuild our ERP system (160 projects) takes under a minute to compile. A sample command line would be:

cd c:\Solution\
c:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild ERP.sln /m:4 /v:m /property:Configuration=Release;ToolsVersion=2.0;CacheVersion=2.0 /fileLogger /fileLoggerParameters:Logfile=C:\ERP.log;Verbosity=minimal

where /m: is the # of cpu cores in your computer, and /v: is the verbosity of the output displayed to the screen (flags are: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]).

Another optimization technique we use is to use multiple solutions. Our main ERP solution contains all the projects for the system. We then have individual solutions for each project area, ie accounting, inventory, logistics, etc. The big solution is only used when doing a full compile of the system (via msbuild). When working in visual studio we only open the sub-solutions which contain a limited subset of projects making the compiles much faster.

1
  • Thank you! I will experiment with your idea on our project. Feb 18, 2012 at 16:21
2

This depends on which language you've chosen. For C++ apps, its easy - split your solution into components and build them separately, then link against the lib files (I recommend copying the compiled lib file into a single directory for the entire project, and keep all shared headers in a single directory too - use the Project Settings to set the path to these). This means you don't need to hold the entire thing in a single solution. You can create a new 'master' solution to build everything for use in a build server, but TBH its easier just to get the build server to build each component one after the other.

For .NET apps, its slightly different, once you have dependencies to assemblies that change, you need to rebuild everything (or get into the use of policy files, or stop using version numbers :) ). Microsoft recommends using a single, huge solution for all your project and only split it if it becomes "too large to load in Visual Studio". However, they describe how to use "partitioned solutions" and "multiple solutions" - you want the latter. this is the most complex as it requires careful handling of references. In summary, you should use file references only and create a script to build each solution in turn, in the correct order.

I wish MS had added a 'reference path' like you can have for C+ libs, then you could build them and copy them to a staging area ready to reference against, but as VS use relative paths, this becomes difficult unless everyone puts their solutions in the same tree structure, though there is a work-around if you use a drive-letter mapped to a directory, VS falls back to using absolute paths.

2

Regarding question number 2 NCrunch or Continuous Test may help. Both run builds and test continuously. With NCrunch you can control how threads and cores are used for building and running tests and you control which you want to include in your current session. I would imagine Continuous Test has similar features but I haven't tried it.

1
  • Thank you. I'll try NCrunch and/or Continuous Test a bit later. I've also found .NET Demon. Unfortunately, it doesn't work properly on my machine. Feb 17, 2012 at 18:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.