Search code examples
.netcachingbuild

can I get .net compiler to do some optimistic caching to speed up the build without refactoring code base into assemblies?


my dotnet code base is pretty big (so I don't feel like undertaking refactor into assemblies project) but doesn't change all that much. The build is real slow, although disk speed is fine - apparently it just takes awhile to compile the thing. So IMHO it would have made good sense for the compiler to cache compiled versions of files that haven't changed since last build in the optimistic expectation that no change in another file broke the module. Then if the optimistic assumption proved invalid, the full build could be undertaken. Well, I am pretty sure that things like that are often done while using Java and C++ compilers.

Could something like that be done here in dotnet? If not, why not :-) ?


Solution

  • Visual Studio doesn't rebuild an assembly unless it has to. It "has to" when any of the following change:

    • Assembly properties such as Target CPU/Framework
    • Dependencies in referenced assemblies (if object A1 in assembly A requires B1 in B, and B1 changes, assemblies A and B must be rebuilt)
    • Source code that will compile into the assembly (obviously)

    Also, build speed is less dependent on pure code count, or even class count, but the number of projects being built. Given a constant number of lines of code that must be fully rebuilt, a solution that builds into one assembly will build faster than a solution that builds into 10 assemblies, because there is a lot of overhead inherent in building an assembly that is repeated on each assembly.

    Here are some basic tips to increase build speed:

    • Try to keep changes at as "high" a level in the assembly reference hierarchy as possible. When A is dependent on B and B is dependent on C, if A changes, only A has to be rebuilt, but if B or C change, anything higher must also be rebuilt. This isn't always possible, but reducing the number of assemblies will reduce this hierarchy so even when you have to rebuild a lower one, there are fewer other assemblies reliant on it.
    • Loosely couple your code by using interfaces for any cross-assembly dependency, and segregate interfaces into their own assembly. Class A dependent on a class B will have to be rebuilt if B changes. However, if A is instead dependent on an interface I which B implements, A won't have to be rebuilt if B changes; only if I does (which is far less common). However, VS builds assemblies; if I is in the assembly with B, the assembly containing A will have to be rebuilt if B changes even though I didn't.
    • Create build configurations that only build what is absolutely necessary for that configuration. A Debug build should not rebuild the installer. By the same token, a Release build should not rebuild testing assemblies. However, by default, new projects are set to be included in every build configuration, so you have to maintain these configurations regularly.
    • On the installer front, see if you can separate building that into a configuration all its own. Installers are easily the slowest single build of any solution rebuild; first they double-check that all assemblies are built, then they collect everything that they need to include and archive it into a CAB, that is THEN encapsulated with the install logic in the MSI. Avoid building this unless you are actually producing a release candidate.
    • Only do a "Rebuild Solution" when you have to. Rebuild Solution performs a "Clean" plus a "Build", resulting in EVERYTHING having to be recreated.
    • Minimize post-build actions. Similarly to creating configs that cut out unneeded assemblies, creating configs that allow you to skip post-build actions when not needed, or simply rearranging your solution so the build ends up in the right place to begin with, will speed you up considerably.
    • Tools like ReSharper or SVN clients, and indexing helpers go crazy when you rebuild, reanalyzing the new assemblies, determining changes, etc. Make sure the Windows Indexing service does not index your source code directories or any build output locations, turn off ReSharper Solution Analysis, and don't include the build output in SVN versioning.