Monday 2 September 2013

Improving Build/Start Up Time

In fairness, there's nothing better to do while
waiting for compilations
I've recently had the pleasure of upgrading to Visual Studio 2012 and for the most part, I love it. However, I've noticed that debugging my web application has become a very time consuming event. From hitting the F5 button to getting to my start up page, it was taking over 3 minutes and needless to say, it was driving me crazy and was seriously affecting my productivity. The xkcd comic on your right may just point to why...

For the sake of my sanity, I set out to find out how to improve this and I've now got that time down to 20-30 seconds. Here's what I've done...

Web.config Changes

There's a couple of changes you can make in order to speed things up. I should say these should only be applied to your local development environment. They're not changes that should be applied to a production environment as they'll have a direct impact on your application's performance.

Firstly, the configuration tag has two attributes you should make use of. There's the batch attribute and the optimizeCompilation attribute. You should set the batch attribute to false and the optimizeCompilation attribute to true, so your tag should look something like this:

<compilation debug="true" batch="false" optimizeCompilations="true" />

Let me explain what this does. First off, the batch attribute. By default, this is set to true and what this means is that when your web application starts up, ASP.NET will pre-compile all your un-compiled files (aspx, ascx files for example) in one big batch. Depending on the size of your application, this can significantly increase your load time. By setting it to false, this will no longer occur and instead, the file will be compiled as and when you access it. That means when you visit a particular page, the load up time for the first time you access that page will be a little slower as it'll need to be compiled but the chances are, if you're debugging a particular problem, you're only going to be visiting a very small subset of the total files that get compiled when the batch attribute is set to true so overall, you'll be saving yourself a significant portion of time. For more info, check out the MSDN documentation.

The optimizeCompilations tag is a bit of an odd one. I can't seem to find any documentation about it apart from this blog post so I don't know if it's valid in .NET 4 (Although I use it in my applications and it seems to do the job). Anyway, the reason this is helpful is that by default every time you change a file in the bin directory, the global.asax file or anything under the App_Code directory, the application is re-compiled during start up (the same re-compile process we spoke about above). By setting this to true, this re-compilation no longer occurs. Now this can cause problems which is why it's not turned on be default (more info about that can be found on the blog post mentioned above) but in the majority, if you're like me, you're usually changing method implementations rather then creating or change method specifications. So, turning it on means no more recompilations, again saving more time on start up.

Fusion Log

For those of you that don't know, fusion is a tool that enables you to log DLL binds to disk (more info on this tool can be here). This is particularly helpful when at runtime you're getting errors about DLL versions or particular DLLs not being found and you can't work out why. The log will tell you where ASP.NET is looking for those DLLs, what it's finding and whether or not it fails. This can be a very handy tool. 
In .NET 3.5, I found that it was sometimes a little unreliable. I'd turn on logging and the logs wouldn't be generated. It was a tad frustrating it must be admitted. In .NET 4, I don't have this problem and logs seem to be generated as you'd expect. The problem with this is that creating these logs takes time and if you happen to have hit the "Log All Binds" option and then forgot about it, you'll notice a significant performance decrease.
Long story short, only log binds if you absolutely need to and make sure it's turned off when you're not using it.

Application_Start

Application_Start is a method in the global.asax file and it'll fire when when the application domain starts up. This is great but if you're running code in there then it'll obviously effect load up time. So, if you don't need to run that code, don't. I know in our application we have features that are initiated in that method. If I'm not testing one of those features then I don't need it enabled which helps speed up the application start up time.

Solution Changes

Finally, you can make a few changes to your solution to ensure only what you need to be built, is built. 

Firstly, do a full re-build of your application so that all necessary DLLs are generated. Then, unload any projects you're not working on. If you change a class or method in one project, Visual Studio will compile all projects that have references to that project. Unloading those projects will ensure they're not rebuilt saving you some precious seconds on your build time.

Secondly, if you right click on the solution at the top of the solution explorer within Visual Studio, you can select "Configuration Manager". In here you can un-tick the "build" option on all projects that you're not working on. As with the option above, this will ensure un-neccesary projects aren't built. What it does mean is that when you change code in a project that you've marked not to be built, you have to explicitly build that project otherwise your changes won't be picked up.

Warning. These solution changes do have down sides. If you change a method signature within a project and projects that reference that have not been built, then any errors caused by that change will not be picked up at compile time. With that in mind, it's well worth compiling everything before committing/pushing/releasing any code, just to ensure everything compiles as you'd expect.

And that's all I've got. If you've got any other tips or tricks regarding application start up time then I'd love to hear them. Very few things frustrate me as much as waiting for the web applications start up screen to actually load.

Happy coding!