adamralph/minver

Is it time to revisit the MSBuild task idea?

bording opened this issue · 2 comments

@adamralph After spending some time looking at build logs in the ServiceControl repo, I noticed that MinVer was showing up as either the first or second most expensive task in the entire build. It varies from build to build, but in general it's showing as taking up ~25 seconds of build time. Since builds are parallel, that's not wall clock time, but that's often as much or more time that csc itself takes.

I wanted to see where all that time was coming from, so I've spiked a few changes, and the results are interesting!

The first thing I started with was changing the main MinVer project over to an MSBuild task and calling that from the targets file instead of having to run a separate process (dotnet MinVer.dll).

After running a few builds, that change alone had the total build time for the MinVer task down to ~12 seconds.

The next thing I wanted to try was removing the external calls out to git. I replaced the git calls with LibGit2Sharp instead, and that had a further reduction to ~6 seconds.

There was one final thing I wanted to try. Since everything was now running entirely inside the MSBuild process, there are APIs you can use to cache results that can be re-used by tasks across the entire build.

When I wired those up, for the normal parallel build, that got the total task execution time down to ~3 seconds. Looking at how the projects were scheduled, I would see that ~20 started up and didn't have cached info, but then the remaining ~40 basically took no time at all since they could use the cached version.

Overall, the total build time has decreased with these changes, though it varies run to run because of MSBuild running things in parallel by default.

However, if I run the build with -m:1, that really shows the difference.

Before:

image

After:
image

Since nothing is running in parallel in those builds, those are all wall clock times (more or less) so MinVer completely disappears from the expensive tasks list. Digging into that build log, I can see that the first time it runs in the build it runs the logic and then caches the result. Every other invocation can use that cached result.

What do you think? Does this sound interesting enough to look into taking this beyond my spike?

@adamralph I went ahead and pushed up my spike branch here: https://github.com/bording/minver/tree/msbuild-task-spike

Let me know when you want to discuss!

@bording thanks, I'll take a look ASAP.