We finally decided to do something about the time we spend waiting for the pre-check-in build to run. Our check-in dance starts with running a rake script to compile our code, run the associated unit and integration tests, and create deployment Zip files. This entire process takes ~96 seconds on an Intel Core i7-2600K CPU as follows:
- Compile – 21 seconds
- Run tests – 58 seconds
- Build Zip files – 17 seconds
NUnit is clearly the biggest time consumer. A quick check of the task manager while the tests are running shows the following.
|From blog images|
A Google search for ready made solutions found PNUnit (a distributed version of NUnit), MBUnit (requires marking assembly, test fixtures, and/or tests as [Parallelizable]), and this StackOverflow question which led us to an inactive open source project called NUnit.MultiCore on Codeplex. We decided to fork the latter.
We modified the code as follows:
- Make it run all test fixtures in parallel by default – no test project code changes required
- Use C# Parallel.ForEach in place of explicit threading
- Change Main to return a result code so it works with Continuous Integration
- Make the output more closely resemble that of NUnit
Introducing this tool into our build process reduced our average run time to 66 seconds and the test portion to 28 seconds by making more effective use of the processor cores.
|From blog images|
The main problem we encountered in converting our test projects to run in parallel involved RhinoMocks which, it turns out, isn’t thread safe. So we forked a copy from Ayende and made the appropriate changes.
We also noticed that the albacore msbuild task doesn’t support configuring MSBuild to use the /m switch to parallelize the compilation. So we forked a copy of albacore and added that capability.
This reduced our compile time from 21 seconds to 19 seconds.
We’re quite happy with the speed up we’ve gained so far and we have identified additional time savings that can gained in the Zip file creation portion.