Very slow compile times on Visual Studio 2005 - c#

We are getting very slow compile times, which can take upwards of 20+ minutes on dual core 2GHz, 2G Ram machines.
A lot of this is due to the size of our solution which has grown to 70+ projects, as well as VSS which is a bottle neck in itself when you have a lot of files. (swapping out VSS is not an option unfortunately, so I don't want this to descend into a VSS bash)
We are looking at merging projects. We are also looking at having multiple solutions to achieve greater separation of concerns and quicker compile times for each element of the application. This I can see will become a DLL hell as we try to keep things in synch.
I am interested to know how other teams have dealt with this scaling issue, what do you do when your code base reaches a critical mass that you are wasting half the day watching the status bar deliver compile messages.
UPDATE
I neglected to mention this is a C# solution. Thanks for all the C++ suggestions, but it's been a few years since I've had to worry about headers.
EDIT:
Nice suggestions that have helped so far (not saying there aren't other nice suggestions below, just what has helped)
New 3GHz laptop - the power of lost utilization works wonders when whinging to management
Disable Anti Virus during compile
'Disconnecting' from VSS (actually the network) during compile - I may get us to remove VS-VSS integration altogether and stick to using the VSS UI
Still not rip-snorting through a compile, but every bit helps.
Orion did mention in a comment that generics may have a play also. From my tests there does appear to be a minimal performance hit, but not high enough to sure - compile times can be inconsistent due to disc activity. Due to time limitations, my tests didn't include as many Generics, or as much code, as would appear in live system, so that may accumulate. I wouldn't avoid using generics where they are supposed to be used, just for compile time performance
WORKAROUND
We are testing the practice of building new areas of the application in new solutions, importing in the latest dlls as required, them integrating them into the larger solution when we are happy with them.
We may also do them same to existing code by creating temporary solutions that just encapsulate the areas we need to work on, and throwing them away after reintegrating the code. We need to weigh up the time it will take to reintegrate this code against the time we gain by not having Rip Van Winkle like experiences with rapid recompiling during development.

The Chromium.org team listed several options for accelerating the build (at this point about half-way down the page):
In decreasing order of speedup:
Install Microsoft hotfix 935225.
Install Microsoft hotfix 947315.
Use a true multicore processor (ie. an Intel Core Duo 2; not a Pentium 4 HT).
Use 3 parallel builds. In Visual Studio 2005, you will find the option in Tools > Options... > Projects and Solutions > Build and Run > maximum number of parallel project builds.
Disable your anti-virus software for .ilk, .pdb, .cc, .h files and only check for viruses on modify. Disable scanning the directory where your sources reside. Don't do anything stupid.
Store and build the Chromium code on a second hard drive. It won't really speed up the build but at least your computer will stay responsive when you do gclient sync or a build.
Defragment your hard drive regularly.
Disable virtual memory.

We have nearly 100 projects in one solution and a dev build time of only seconds :)
For local development builds we created a Visual Studio Addin that changes Project references to DLL references and unloads the unwanted projects (and an option to switch them back of course).
Build our entire solution once
Unload the projects we are not currently working on and change all project references to DLL references.
Before check-in change all references back from DLL to project references.
Our builds now only take seconds when we are working on only a few projects at a time. We can also still debug the additional projects as it links to the debug DLLs. The tool typically takes 10-30 seconds to make a large number of changes, but you don't have to do it that often.
Update May 2015
The deal I made (in comments below), was that I would release the plugin to Open Source if it gets enough interest. 4 years later it has only 44 votes (and Visual Studio now has two subsequent versions), so it is currently a low-priority project.

I had a similar issue on a solution with 21 projects and 1/2 million LOC. The biggest difference was getting faster hard drives. From the performance monitor the 'Avg. Disk Queue' would jump up significantly on the laptop indicating the hard drive was the bottle neck.
Here's some data for total rebuild times...
1) Laptop, Core 2 Duo 2GHz, 5400 RPM Drive (not sure of cache. Was standard Dell inspiron).
Rebuild Time = 112 seconds.
2) Desktop (standard issue), Core 2 Duo 2.3Ghz, single 7200RPM Drive 8MB Cache.
Rebuild Time = 72 seconds.
3) Desktop Core 2 Duo 3Ghz, single 10000 RPM WD Raptor
Rebuild Time = 39 seconds.
The 10,000 RPM drive can not be understated. Builds where significantly quicker plus everything else like displaying documentation, using file explorer was noticable quicker. It was a big productivity boost by speeding the code-build-run cycle.
Given what companies spend on developer salaries it is insane how much they can waste buy equiping them with the same PCs as the receptionist uses.

For C# .NET builds, you can use .NET Demon. It's a product that takes over the Visual Studio build process to make it faster.
It does this by analyzing the changes you made, and builds only the project you actually changed, as well as other projects that actually relied on the changes you made. That means if you only change internal code, only one project needs to build.

Turn off your antivirus. It adds ages to the compile time.

Use distributed compilation. Xoreax IncrediBuild can cut compilation time down to few minutes.
I've used it on a huge C\C++ solution which usually takes 5-6 hours to compile. IncrediBuild helped to reduce this time to 15 minutes.

Instructions for reducing your Visual Studio compile time to a few seconds
Visual Studio is unfortunately not smart enough to distinguish an assembly's interface changes from inconsequential code body changes. This fact, when combined with a large intertwined solutions, can sometimes create a perfect storm of unwanted 'full-builds' nearly every time you change a single line of code.
A strategy to overcome this is to disable the automatic reference-tree builds. To do this, use the 'Configuration Manager' (Build / Configuration Manager...then in the Active solution configuration dropdown, choose 'New') to create a new build configuration called 'ManualCompile' that copies from the Debug configuration, but do not check the 'Create new project configurations' checkbox. In this new build configuration, uncheck every project so that none of them will build automatically. Save this configuration by hitting 'Close'. This new build configuration is added to your solution file.
You can switch from one build configuration to another via the build configuration dropdown at the top of your IDE screen (the one that usually shows either 'Debug' or 'Release'). Effectively this new ManualCompile build configuration will render useless the Build menu options for: 'Build Solution' or 'Rebuild Solution'. Thus, when you are in the ManualCompile mode, you must manually build each project that you are modifying, which can be done by right-clicking on each affected project in the Solution Explorer, and then selecting 'Build' or 'Rebuild'. You should see that your overall compile times will now be mere seconds.
For this strategy to work, it is necessary for the VersionNumber found in the AssemblyInfo and GlobalAssemblyInfo files to remain static on the developer's machine (not during release builds of course), and that you don't sign your DLLs.
A potential risk of using this ManualCompile strategy is that the developer might forget to compile required projects, and when they start the debugger, they get unexpected results (unable to attach debugger, files not found, etc.). To avoid this, it is probably best to use the 'Debug' build configuration to compile a larger coding effort, and only use the ManualCompile build configuration during unit testing or for making quick changes that are of limited scope.

If this is C or C++, and you're not using precompiled headers, you should be.

We had a 80+ projects in our main solution which took around 4 to 6 minutes to build depending on what kind of machine a developer was working. We considered that to be way too long: for every single test it really eats away your FTEs.
So how to get faster build times? As you seem to already know it is the number of projects that really hurt the buildtime. Of course we did not want to get rid of all our projects and simply throw all sourcefiles into one. But we had some projects that we could combine nevertheless: As every "Repository project" in the solution had its own unittest project, we simply combined all the unittest projects into one global-unittest project. That cut down the number of projects with about 12 projects and somehow saved 40% of the time to build the entire solution.
We are thinking about another solution though.
Have you also tried to setup a new (second) solution with a new project? This second solution should simply incorporates all files using solution folders. Because you might be surprised to see the build time of that new solution-with-just-one-project.
However, working with two different solutions will take some carefull consideration. Developers might be inclined to actually -work- in the second solution and completely neglect the first. As the first solution with the 70+ projects will be the solution that takes care of your object-hierarchy, this should be the solution where your buildserver should run all your unittests. So the server for Continous Integration must be the first project/solution. You have to maintain your object-hierarchy, right.
The second solution with just one project (which will build mucho faster) will than be the project where testing and debugging will be done by all developers. You have to take care of them looking at the buildserver though! If anything breaks it MUST be fixed.

Make sure your references are Project references, and not directly to the DLLs in the library output directories.
Also, have these set to not copy locally except where absolutely necessary (The master EXE project).

I posted this response originally here:
https://stackoverflow.com/questions/8440/visual-studio-optimizations#8473
You can find many other helpful hints on that page.
If you are using Visual Studio 2008, you can compile using the /MP flag to build a single project in parallel. I have read that this is also an undocumented feature in Visual Studio 2005, but have never tried myself.
You can build multiple projects in parallel by using the /M flag, but this is usually already set to the number of available cores on the machine, though this only applies to VC++ I believe.

I notice this question is ages old, but the topic is still of interest today. The same problem bit me lately, and the two things that improved build performance the most were (1) use a dedicated (and fast) disk for compiling and (2) use the same outputfolder for all projects, and set CopyLocal to False on project references.
Some additional resources:
https://stackoverflow.com/questions/8440/visual-studio-optimizations
http://weblogs.asp.net/scottgu/archive/2007/11/01/tip-trick-hard-drive-speed-and-visual-studio-performance.aspx
http://arnosoftwaredev.blogspot.com/2010/05/how-to-improve-visual-studio-compile.html
http://blog.brianhartsock.com/2009/12/22/analyzing-visual-studio-build-performance/

Some analysis tools:
tools->options->VC++ project settings -> Build Timing = Yes
will tell you build time for every vcproj.
Add /Bt switch to compiler command line to see how much every CPP file took
Use /showIncludes to catch nested includes (header files that include other header files), and see what files could save a lot of IO by using forward declarations.
This will help you optimize compiler performance by eliminating dependencies and performance hogs.

Before spending money to invest in faster hard drives, try building your project entirely on a RAM disk (assuming you have the RAM to spare). You can find various free RAM disk drivers on the net. You won't find any physical drive, including SSDs, that are faster than a RAM disk.
In my case, a project that took 5 minutes to build on a 6-core i7 on a 7200 RPM SATA drive with Incredibuild was reduced by only about 15 seconds by using a RAM disk. Considering the need to recopy to permanent storage and the potential for lost work, 15 seconds is not enough incentive to use a RAM disk and probably not much incentive to spend several hundreds of dollars on a high-RPM or SSD drive.
The small gain may indicate that the build was CPU bound or that Windows file caching was rather effective, but since both tests were done from a state where the files weren't cached, I lean heavily towards CPU-bound compiles.
Depending on the actual code you're compiling your mileage may vary -- so don't hesitate to test.

How big is your build directory after doing a complete build? If you stick with the default setup then every assembly that you build will copy all of the DLLs of its dependencies and its dependencies' dependencies etc. to its bin directory. In my previous job when working with a solution of ~40 projects my colleagues discovered that by far the most expensive part of the build process was copying these assemblies over and over, and that one build could generate gigabytes of copies of the same DLLs over and over again.
Here's some useful advice from Patrick Smacchia, author of NDepend, about what he believes should and shouldn't be separate assemblies:
http://codebetter.com/patricksmacchia/2008/12/08/advices-on-partitioning-code-through-net-assemblies/
There are basically two ways you can work around this, and both have drawbacks. One is to reduce the number of assemblies, which is obviously a lot of work. Another is to restructure your build directories so that all your bin folders are consolidated and projects do not copy their dependencies' DLLs - they don't need to because they are all in the same directory already. This dramatically reduces the number of files created and copied during a build, but it can be difficult to set up and can leave you with some difficulty pulling out only the DLLs required by a specific executable for packaging.

Perhaps take some common functions and make some libraries, that way the same sources are not being compiled over and over again for multiple projects.
If you are worried about different versions of DLLs getting mixed up, use static libraries.

Turn off VSS integration. You may not have a choice in using it, but DLLs get "accidentally" renamed all the time...
And definitely check your pre-compiled header settings. Bruce Dawson's guide is a bit old, but still very good - check it out: http://www.cygnus-software.com/papers/precompiledheaders.html

I have a project which has 120 or more exes, libs and dlls and takes a considerable time to build. I use a tree of batch files that call make files from one master batch file. I have had problems with odd things from incremental (or was it temperamental) headers in the past so I avoid them now. I do a full build infrequently, and usually leave it to the end of the day while I go for a walk for an hour (so I can only guess it takes about half an hour). So I understand why that is unworkable for working and testing.
For working and testing I have another set of batch files for each app (or module or library) which also have all the debugging settings in place -- but these still call the same make files. I may switch DEBUG on of off from time to time and also decide on builds or makes or if I want to also build libs that the module may depend on, and so on.
The batch file also copies the completed result into the (or several) test folders. Depending of the settings this completes in several seconds to a minute (as opposed to say half an hour).
I used a different IDE (Zeus) as I like to have control over things like .rc files, and actually prefer to compile from the command line, even though I am using MS compliers.
Happy to post an example of this batch file if anyone is interested.

Disable file system indexing on your source directories (specifically the obj directories if you want your source searchable)

If this is a web app, setting batch build to true can help depending on the scenario.
<compilation defaultLanguage="c#" debug="true" batch="true" >
You can find an overview here: http://weblogs.asp.net/bradleyb/archive/2005/12/06/432441.aspx

You also may want to check for circular project references. It was an issue for me once.
That is:
Project A references Project B
Project B references Project C
Project C references Project A

One cheaper alternative to Xoreax IB is the use of what I call uber-file builds. It's basically a .cpp file that has
#include "file1.cpp"
#include "file2.cpp"
....
#include "fileN.cpp"
Then you compile the uber units instead of the individual modules. We've seen compile times from from 10-15 minutes down to 1-2 minutes. You might have to experiemnt with how many #includes per uber file make sense. Depends on the projects. etc. Maybe you include 10 files, maybe 20.
You pay a cost so beware:
You can't right click a file and say "compile..." as you have to exclude the individual cpp files from the build and include only the uber cpp files
You have to be careful of static global variable conflicts.
When you add new modules, you have to keep the uber files up to date
It's kind of a pain, but for a project that is largely static in terms of new modules, the intial pain might be worth it. I've seen this method beat IB in some cases.

If it's a C++ project, then you should be using precompiled headers. This makes a massive difference in compile times. Not sure what cl.exe is really doing (with not using precompiled headers), it seems to be looking for lots of STL headers in all of the wrong places before finally going to the correct location. This adds entire seconds to every single .cpp file being compiled. Not sure if this is a cl.exe bug, or some sort of STL problem in VS2008.

Looking at the machine that you're building on, is it optimally configured?
We just got our build time for our largest C++ enterprise-scale product down from 19 hours to 16 minutes by ensuring the right SATA filter driver was installed.
Subtle.

There's undocumented /MP switch in Visual Studio 2005, see http://lahsiv.net/blog/?p=40, which would enable parallel compilation on file basis rather than project basis. This may speed up compiling of the last project, or, if you compile one project.

When choosing a CPU: L1 cache size seems to have a huge impact on compilation time. Also, it is usually better to have 2 fast cores than 4 slow ones. Visual Studio doesn't use the extra cores very effectively. (I base this on my experience with the C++ compiler, but it is probably also true for the C# one.)

I'm also now convinced there is a problem with VS2008. I'm running it on a dual core Intel laptop with 3G Ram, with anti-virus switched off. Compiling the solution is often quite slick, but if I have been debugging a subsequent recompile will often slow down to a crawl. It is clear from the continuous main disk light that there is a disk I/O bottleneck (you can hear it, too). If I cancel the build and shutdown VS the disk activity stops. Restart VS, reload the solution and then rebuild, and it is much faster. Unitl the next time
My thoughts are that this is a memory paging issue - VS just runs out of memory and the O/S starts page swapping to try to make space but VS is demanding more than page swapping can deliver, so it slows down to a crawl. I can't think of any other explanation.
VS definitely is not a RAD tool, is it?

Does your company happen to use Entrust for their PKI/Encryption solution by any chance? It turns out, we were having abysmal build performance for a fairly large website built in C#, taking 7+ minutes on a Rebuild-All.
My machine is an i7-3770 with 16gb ram and a 512GB SSD, so performance should not have been that bad. I noticed my build times were insanely faster on an older secondary machine building the same codebase. So I fired up ProcMon on both machines, profiled the builds, and compared the results.
Lo and behold, the slow-performing machine had one difference -- a reference to the Entrust.dll in the stacktrace. Using this newly acquired info, I continued to search StackOverflow and found this: MSBUILD (VS2010) very slow on some machines. According to the accepted answer the problem lies in the fact the Entrust handler was processing the .NET certificate checks instead of the native Microsoft handler. Tt is also suggested that Entrust v10 solves this issue that is prevalent in Entrust 9.
I currently have it uninstalled and my build times plummeted to 24 seconds. YYMV with the number of projects you currently are building and may not directly address the scaling issue you were inquiring about. I will post an edit to this response if I can provide a fix without resorting to an uninstallation the software.

It's sure there's a problem with VS2008. Because the only thing I've done it's to install VS2008 for upgrading my project which has been created with VS2005.
I've only got 2 projects in my solution. It isn't big.
Compilation with VS2005 : 30 secondes
Compilation with VS2008 : 5 minutes

Nice suggestions that have helped so far (not saying there aren't other nice suggestions below, if you are having issues, I recommend reading then, just what has helped us)
New 3GHz laptop - the power of lost utilization works wonders when whinging to management
Disable Anti Virus during compile
'Disconnecting' from VSS (actually the network) during compile - I may get us to remove VS-VSS integration altogether and stick to using the VSS UI
Still not rip-snorting through a compile, but every bit helps.
We are also testing the practice of building new areas of the application in new solutions, importing in the latest dlls as required, them integrating them into the larger solution when we are happy with them.
We may also do them same to existing code by creating temporary solutions that just encapsulate the areas we need to work on, and throwing them away after reintegrating the code. We need to weigh up the time it will take to reintegrate this code against the time we gain by not having Rip Van Winkle like experiences with rapid recompiling during development.
Orion did mention in a comment that generics may have a play also. From my tests there does appear to be a minimal performance hit, but not high enough to sure - compile times can be inconsistent due to disc activity. Due to time limitations, my tests didn't include as many Generics, or as much code, as would appear in live system, so that may accumulate. I wouldn't avoid using generics where they are supposed to be used, just for compile time performance

Related

Avoid significant amounts of packages and binaries when using Roslyn with Nuget

I'm trying to make use of Roslyn in my application. I added the NuGet package for that (Microsoft.CodeAnalysis.CSharp). It turns out that this package depends on many others:
Most of them seem unused on the .NET Framework (e.g. System.Runtime which provides types such as Int32).
There is an incredible contrast between the size of those packages and what is actually being used. A lot of the data appear to be translations:
(I'm not saying someone did a bad job here. I'm not competent enough to make that determination. I just want to find out how to deal with this, see below.)
It seems like a bad idea to check all of that in to source control. If I update those packages every few months then then repository will bloat by gigabytes from all those files over time. I'm also worried about IDE speed and frankly about confusing myself in this huge sea of packages.
Package restore cannot be used due to security concerns and reliance on another company's ongoing service for our source code to be able to build. By "other company" I mean that I need to trust Microsoft and the package authors to be available at all times, not send me a virus and not remove old versions causing my app to break. If I download just once, or every few month, the exposure is greatly reduced.
How would I best minimize the source control impact of using Roslyn?
I really hope I will be able to put the packages into source control. I hope there is a way to remove all the packages I don't need and restrict them to what ends up in the bin folder.
You shouldn't check the packages folder to source control; that'll make you sad. It sounds like your real problem is concern of the reliability of nuget.org or packages existing. If that's a concern you might want to consider just storing the .nupkg files in a place where you control and can keep them around. You might want to take a look at these instructions of how you could run your own server, which can be as low tech as "have a network drive".
You could also check in the .nupkg files and then use that as your feed, which would at least reduce the number of files you need to manage. At least those will be smaller and compressed vs. the uncompressed folders.

Continuous Integration for stack with Visual C++ and C#

Please recommend a good continuous integration that would build and integrate with the .net stack and the visual c++ as well.
Some recommendations I have got are
Jenkins
CruiseControl
Teamcity
Because of the polyglot nature of the project, which continuous integration solution would you recommend?
I have used all three over several years. Some of the answers below state that most of the work will be producing your own build scripts. This has been true in my experience as well. We use a combination of MSBuild and Powershell scripts for our build process, which can be run under just about any CI tool, so picking one comes down to what you're looking for in terms of customization, integration with other systems, performance, and ease of use.
Short answer:
I recommend Jenkins. So far it seems to be the best combination of the above qualities. It has a ton of plugins, some localization and is actively developed by the OSS community.
Long answer:
I started with Cruise Control .Net. It was easily configurable with a text file and I found it highly reliable. However, we moved away from it because Thoughtworks was moving toward a paid product (Cruise, now Go) and future development was in question. A new team has since forked the project but there is little word about future development since.
We moved to TeamCity, which is free and has a great ajax-y UI. It is easy to setup and get going and has a lot of features for distributed builds. We quit using TeamCity for several reasons. The server does a ton of stuff and it was a bit overkill for our basic needs. Even so, it was not very customizable (see Time Zones and notification contents) and we often found the administration UI confusing. That was all still okay, but we also had steadily worsening performance problems. We started with a standard HSSQLDB out-of-the-box, moved our installation to SQL server when we started experiencing degraded performance, then had to quit using the server at all as performance continued to degrade over time. I'm not sure what the culprit was but I couldn't find any cleanup to do that would explain the constantly worsening performance as the Tomcat web server fought with SQL Server for resources, even when there were no active builds running. I am sure it's my fault and I was missing some crucial setting or needed to feed the server more memory, but this is a shared utility box, we did not have these issues with CC.Net, and most of all, I am not a Java/Tomcat guy and don't have a lot of extra time to keep fighting with these issues.
We've moved to Jenkins now. It seems to be working fine so far but we've only been with it a short while. It was easy to set up, does not seem to be taking nearly as many resources as TeamCity and has a ridiculous number of plugins. The only downside so far is like many OSS products, it does not seem to have the best documentation and it does so much that I may be tweaking knobs for a while to get it set up the way we want.
Between CruiseControl and TeamCity, TeamCity is faster and easier to set up, but you may need to check on licensing for it. I can't speak to Jenkins, never having used it.
Jenkins has the big advantage of being very extensible (currently over 400 plugins), which allows you to combine it with a huge number of other tools. So it gives you complete freedom in your other tool choices. I recently read that this is one problem of TeamCity, that you get locked in using the whole stack of tools (e.g. using SVN or Git as version control system will not be possible).
I am using Jenkins myself for our projects which has both Java and C++ code, and I am very happy with the tool. We had CruiseControl before, and have not once regretted the switch.
I have tried both Cruise Control and Jenkins, and Jenkins impressed me with very fast and user-friendly set up.
The three you list are all sensible choices, and the main problem will be producing the build script(s) needed to do produce the build artifact(s). If you manage to make them do everything needed, changing CI system shouldn't be a big issue.
After implementing all three in different shops, I'd chose all of the above. Pick one.

Building takes long time. How fight with that?

Speaking about compiled languages (c# in my case) I think that problem would always remain, no matter how performant your develop machine is. Build time could be more or less depending on concrete environment, but often it's enough to make your attention wanna move from your task to something else like stackoverflow, youtube, twitter etc. and it's just very annoying.
I'm happy for java developers because of Java's dynamic class loading, but what can .net (and others) developers do to make build process less painful and obtrusive?
We use multiple build configurations to trade-off between speed and a comprehensive build.
A full build does time-consuming things like FX cop analysis, ASP.NET compilation, all unit test projects, Entity Framework view pre-generation, etc.
A "fast build" typically takes just a few seconds and those the bare minimum needed to get the project running.
Developers switch between the full build and the fast build throughout their workflow, as needed.
Don't the class files have to be build as well? Wouldn't that just put the workload to runtime in contrast to compile time? That's not really a difference isn't it? The bigger software grows, naturally, the longer it takes to build it, depending on the machine and not on the language or framework - this is the tradeoff for things like strong typing, interpreted byte code (or binary code depending on the language/compiler) instead of interpreted source code at each run (as you have with php and python etc). I don't think java improves things much, there will a timeframe you have to build your application in.
I think in comparision to C and C++ both C# and java have improved immensely on the account of compile time.
Just use the time for slacking off:
source
Some things to try:
Defragment the drive containing your source code
Exclude your source code folders from the virus scanner
Exclude your source code folders from the Windows Search indexer
Disable any Visual Studio extensions that you are not using
The remark in your question about one's attention wandering off-task reminded me of this Joel on Software post.
So investing in solid-state disks (since I'm assuming you're talking about the build process on a dev box while you're developing and debugging) could help.
Besides, making your computer faster in general can't hurt, right? :)
In addition to many of the other suggestions to get a faster machine, remove unnecessary projects from your solution, etc, consider Visual Studio 2010 + a multicore machine. VS2010 can take advantage of all of your cores when doing a build. Check out this thread for more on how to set that up.
Are you doing a rebuild all every time or do you have everything in the same assembly? I'm working with quite large projects and my build time isn't that high. I got several assemblies and I only modify a few each time I do changes to the project.
If you find yourself modifying assemblies all over the place, you might try to refactor your code structure. Or maybe you haven't taken yourself time to do unit tests? They do not only help you with the testing, but to get better code structure (hard to test apps with lousy design).
Another alternative is to use tools that speed up builds, for instance: http://www.xoreax.com/
I've worked on some very large C# projects and have rarely seen Debug build times exceed 2 minutes.
What generally sucks time are things like static analysis (e.g. fxcop), unit tests, code signing (if using a code sign service), etc. The easiest way to keep these under control is to either limit them to Release builds or to have a separate build definition for 'Full Build' and exclude these steps from your Debug and Release builds.
If these aren't your problems, look to your computer performance as others have said. Fragmentation, slow build disks, anti-virus, etc.

Will more CPUs/cores help with VS.NET build times?

I was wondering if anyone knew whether Visual Studio .NET had a parallel build process or not? I have a solution with lots of projects, every project has lots of markup/code, lots of types, etc. Just sitting there with intellisense on runs it up to about 700MB. But the build times are really slow and only seem to max out one of my two cpu cores.
Does this mean the build process is single threaded? My solution's build dependency chain isn't linear, so I don't see why it couldn't be building some of the projects in parallel. I remember Joel Spolsky blogging about his new SSD, and how it didn't help with compile times, but he didn't mention which compiler he was using. We're using VS 2005. Anyone know how it's compilation works? And is it any different/better in 2008/2010?
EDIT: Lots of good responses, here, but I'm interested specifically in C# and ASP.NET. No love for us web folks?
MSBuild (which VS uses to do builds, from 2005/.NET2) supports parallel builds. By default VS will set the maximum degree of parallelism to your number of processors. Use Tools | Options | Projects and Solutions | Build and Run to override this default.
Of course any one build might have more limited (or no) capacity to allow parallel builds. E.g. only one assembly in a solution provides no scope to build in parallel. Equally a large number of assemblies with lots of dependencies might block parallelism (A depends on B, C depends on A&B, D depends on C has no scope for parallel builds).
(NB. for C++, in VS 2005 & 2008 uses its own build system, in 2010 C++ will also be built with MSBuild.)
Scott Hanselman has a blog post from a couple years ago that details getting Faster Builds with MSBuild using Parallel Builds and Multicore CPUs that should be of interest. He also has a follow up post Hack: Parallel MSBuilds from within the Visual Studio IDE.
I would suggest that an SSD drive would provide the biggest benefit explicitly for builds
SuperUser which also refutes Joel's article
SO asking for best laptop etc: discussions on SSDs, cores, how VS works etc
Qualifier: I bought an Intel SSD for home use a month or 3 ago. Lordy it's fast and arguably the best piece of kit I've ever bought except for my Voodoo 2...
With VS2k5 it depends on which language you're trying to use. C/C++ has 'experimental' support for multi-threaded building, but this feature isn't officially supported until 2k8 using the /m: switch
I have used parallel builds in Visual Studio 2008. It does speed things up, but has many annoying side effects.
I often get failed builds not because some compilation failed but because VS was unable to write into a locked symbol database. I have also got really messed up Intellisense results. Sometimes I have to repeat the build two or three times to get a final success.

Best practices for large solutions in Visual Studio (2008) [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
We have a solution with around 100+ projects, most of them C#. Naturally, it takes a long time to both open and build, so I am looking for best practices for such beasts. Along the lines of questions I am hoping to get answers to, are:
how do you best handle references between projects
should "copy local" be on or off?
should every project build to its own folder, or should they all build to the same output folder(they are all part of the same application)
Are solutions' folders a good way of organizing stuff?
I know that splitting the solution up into multiple smaller solutions is an option, but that comes with its own set of refactoring and building headaches, so perhaps we can save that for a separate thread :-)
You might be interested in these two MSBuild articles that I have written.
MSBuild: Best Practices For Creating Reliable Builds, Part 1
MSBuild: Best Practices For Creating Reliable Builds, Part 2
Specificially in Part 2 there is a section Building large source trees that you might want to take a look at.
To briefly answer your questions here though:
CopyLocal? For sure turn this off
Build to one or many output folders? Build to one output folder
Solution folders? This is a matter of taste.
Sayed Ibrahim Hashimi
My Book: Inside the Microsoft Build Engine : Using MSBuild and Team Foundation Build
+1 for sparing use of solution folders to help organise stuff.
+1 for project building to its own folder. We initially tried a common output folder and this can lead to subtle and painful to find out-of-date references.
FWIW, we use project references for solutions, and although nuget is probably a better choice these days, have found svn:externals to work well for both 3rd party and (framework type) in-house assemblies. Just get into the habit of using a specific revision number instead of HEAD when referencing svn:externals (guilty as charged:)
Unload projects you don't use often, and buy a SSD. A SSD doesn't improve compile time, but Visual Studio becomes twice faster to open/close/build.
We have a similar problem as we have 109 separate projects to deal with. To answer the original questions based on our experiences:
1. How do you best handle references between projects
We use the 'add reference' context menu option. If 'project' is selected, then the dependency is added to our single, global solution file by default.
2. Should "copy local" be on or off?
Off in our experience. The extra copying just adds to the build times.
3. Should every project build to its own folder, or should they all build to the same output folder(they are all part of the same application)
All of our output is put in a single folder called 'bin'. The idea being that this folder is the same as when the software is deployed. This helps prevents issues that occur when the developer setup is different from the deployment setup.
4. Are solutions folders a good way of organizing stuff?
No in our experience. One person's folder structure is another's nightmare. Deeply nested folders just increase the time it takes to find anything. We have a completely flat structure but name our project files, assemblies and namespaces the same.
Our way of structuring projects relies on a single solution file. Building this takes a long time, even if the projects themselves have not changed. To help with this, we usually create another 'current working set' solution file. Any projects that we are working on get added in to this. Build times are vastly improved, although one problem we have seen is that Intellisense fails for types defined in projects that are not in the current set.
A partial example of our solution layout:
\bin
OurStuff.SLN
OurStuff.App.Administrator
OurStuff.App.Common
OurStuff.App.Installer.Database
OurStuff.App.MediaPlayer
OurStuff.App.Operator
OurStuff.App.Service.Gateway
OurStuff.App.Service.CollectionStation
OurStuff.App.ServiceLocalLauncher
OurStuff.App.StackTester
OurStuff.Auditing
OurStuff.Data
OurStuff.Database
OurStuff.Database.Constants
OurStuff.Database.ObjectModel
OurStuff.Device
OurStuff.Device.Messaging
OurStuff.Diagnostics
...
[etc]
We work on a similar large project here. Solution folders has proved to be a good way of organising things, and we tend to just leave copy local set to true. Each project builds to its own folder, and then we know for each deployable project in there we have the correct subset of the binaries in place.
As for the time opening and time building, that's going to be hard to fix without breaking into smaller solutions. You could investigate parallelising the build (google "Parallel MS Build" for a way of doing this and integrating into the UI) to improve speed here. Also, look at the design and see if refactoring some of your projects to result in fewer overall might help.
In terms of easing the building pain, you can use the "Configuration Manager..." option for builds to enable or disable building of specific projects. You can have a "Project [n] Build" that could exclude certain projects and use that when you're targeting specific projects.
As far as the 100+ projects goes, I know you don't want to get hammered in this question about the benefits of cutting down your solution size, but I think you have no other option when it comes to speeding up load time (and memory usage) of devenv.
What I typically do with this depends a bit on how the "debug" process actually happens. Typically though I do NOT set copy local to be true. I setup the build directory for each project to output everything to the desired end point.
Therefore after each build I have a populated folder with all dll's and any windows/web application and all items are in the proper location. Copy local wasn't needed since the dll's end up in the right place in the end.
Note
The above works for my solutions, which typically are web applications and I have not experienced any issues with references, but it might be possible!
We have a similar issue. We solve it using smaller solutions. We have a master solution that opens everything. But perf. on that is bad. So, we segment up smaller solutions by developer type. So, DB developers have a solution that loads the projects they care about, service developers and UI developers the same thing. It's rare when somebody has to open up the whole solution to get what they need done on a day to day basis. It's not a panacea -- it has it's upsides and downsides. See "multi-solution model" in this article (ignore the part about using VSS :)
I think with solutions this large the best practice should be to break them up. You can think of the "solution" as a place to bring together the necessary projects and perhaps other pieces to work on a solution to a problem. By breaking the 100+ projects into multiple solutions specialized to developing solutions for only a part of the overall problem you can deal with less at a given time there by speeding your interactions with the required projects and simplifying the problem domain.
Each solution would produce the output which it is responsible for. This output should have version information which can be set in an automated process. When the output is stable you can updated the references in dependent projects and solutions with the latest internal distribution. If you still want to step into the code and access the source you can actually do this with the Microsoft symbol server which Visual Studio can use to allow you to step into referenced assemblies and even fetch the source code.
Simultaneous development can be done by specifying interfaces upfront and mocking out the assemblies under development while you are waiting for dependencies that are not complete but you wish to develop against.
I find this to be a best practice because there is no limit to how complex the overall effort can get when you break down it down physically in this manner. Putting all the projects into a single solution will eventually hit an upper limit.
Hope this information helps.
We have about 60+ projects and we don't use solution files. We have a mix of C# and VB.Net projects. The performance was always an issue. We don't work on all the projects at the same time. Each developer creates their own solution files based on the projects they're working on. The solution files doesn't get checked into our source control.
All Class library projects would build to a CommonBin folder at the root of the source directory. Executable / Web Projects build to their individual folder.
We don't use project references, instead file based reference from the CommonBin folder. I wrote a custom MSBuild Task that would inspect the projects and determine the build order.
We have been using this for few years now and have no complaints.
It all has to do with your definition and view on what a solution and a project are. In my mind a solution is just that, a logical grouping of projects that solve a very specific requirement. We develop a large Intranet application. Each application within that Intranet has it's own solution, which may also contain projects for exes or windows services. And then we have a centralized framework with things like base classes and helpers and httphandlers/httpmodules. The base framework is fairly large and is used by all applications. By splitting up the many solutions in this way you reduce the amount of projects required by a solution, as most of them have nothing to do with one another.
Having that many projects in a solution is just bad design. There should be no reason to have that many projects under a solution. The other problem I see is with project references, they can really screw you up eventually, especially if you ever want to split up your solution into smaller ones.
My advice is to do this and develop a centralized framework (your own implementation of Enterprise Library if you will). You can either GAC it to share or you can directly reference the file location so that you have a central store. You could use the same tactic for centralized business objects as well.
If you want to directly reference the DLL you will want to reference it in your project with copy local false (somewhere like c:\mycompany\bin\mycompany.dll). A runtime you will need to add some settings to your app.config or web.config to make it reference a file not in the GAC or runtime bin. In all actuality it doesn't matter if it's copy local or not, or if the dll ends up in the bin or is even in the GAC, because the config will override both of those. I think it is bad practice to copy local and have a messy system. You will most likely have to copy local temporarily if you need to debug into one of those assemblies though.
You can read my article on how to use a DLL globally without the GAC. I really dislike the GAC mostly because it prevents xcopy deployment and does not trigger an autorestart on applications.
http://nbaked.wordpress.com/2010/03/28/gac-alternative/
Set CopyLocal=false will reduce build time, but can cause different issues during deployment time.
There are many scenarios, when you need to have Copy Local’ left to True, e.g.
Top-level projects,
Second-level dependencies,
DLLs called by reflection.
My experience with setting CopyLocal=false wasn't successful. See summary of pro and cons in my blog post "Do NOT Change "Copy Local” project references to false, unless understand subsequences."

Categories

Resources