Anson Horton Profile picture
Jan 3, 2021 22 tweets 4 min read Read on X
Incremental rebuild was a feature of the C# compiler which was meant to increase the throughput after an initial build. It worked on the principle that changes in between builds are localized, and that the information gathered by the compiler from previous builds wouldn't be
entirely invalidated; specifically, some of the information and, indeed, the assembly itself could be updated in an incremental fashion resulting in faster builds.
Both the VS 2002 and VS 2003 compilers exposed this option through the /incr switch on the command line, and the ‘Incremental Rebuild’ option in the Advanced tab of Project Properties. In 2002 incremental rebuild was enabled by default for all project types.
After we shipped 2002 we noticed that we started to get a large number of bugs (internal compiler errors - ICEs – the worst kind) which were a direct result of the incremental rebuild feature.
These bugs derived from the complexities involved in correctly implementing incremental rebuild and the problems associated with testing it. Consequently, for 2003 we fixed all known issues with incremental rebuild but subsequently turned it off by default for all projects.
Incremental build initially seems like a no-brainer win, it can theoretically improve compilation times by significant amounts, in certain cases we saw single assembly build times improve by as much as 6x.
However, and this may seem counter-intuitive at first, incremental rebuild could also lead to longer build times. Why? The feature had several heuristics to determine whether it should do a full rebuild or not.
One of those heuristics was if > 50% of the files being tracked needed to be recompiled. However, in most cases the files that needed to be recompiled aren't simply the files that have changes, but rather the dependency graph between the changed public interface of the types
within the files and those other source files that depend on those types. So, the compiler would do a lot of work to figure out the dependency graph, and occasionally discover it should actually do a full build anyway.
Due to how incremental rebuild worked, it would then throw out all of the work it had done, and simply perform the normal build at that point, increasing the end-to-end time. Incremental rebuild also had a few other implications that were likely non-obvious to folks.
We wanted to update the existing assembly and PDB, but due to the way they are laid out, incrementally updating them meant they would contain the old data as well and we'd just update the pointers (e.g. in the metadata table) to point to the new locations in the file.
That meant the assembly generated from an incremental build was different than what you'd get from a non-incremental build, and both be larger and slower to load.
The slower to load aspect likely wasn't a big deal; however, the different output spoke to one of the major problems that users had with incremental build. In VS 2002 it was entirely possible to build, have the compiler choke and issue an error, and the simply build again
and have it work. This lowered confidence in the compiler (reasonably), and led to odd conclusions about why the compiler was exhibiting this behavior that were unrelated to the incremental flag, because many users didn't even know it was set.
For example, folks might tweak their code, do another build, and have it work - not because of the change they made, but because a non-incremental build happened. There were at least 13 cases that would cause the compiler to bail on doing an incremental rebuild and perform a
full build instead, including things like 'more than 30 successful incremental builds without a full build', which would prevent the PE from getting too bloated over time. So, whether or not the user actually saw the incremental behavior was difficult for them to predict.
All of this led to the decision to cut incremental build in VS 2005. I should mention that this is incremental compilation of the assembly, incremental rebuild of the solution was most decidedly not cut and was greatly improved in VS 2005 through MSBuild.
The funny thing about this one is that we had initially spent significant design, added complexity to the codebase, and effort in validation (every feature added to the language needed to be separately tested in incremental cases) and when we turned it off by default in VS 2003
essentially no one noticed. We had a few folks who mentioned it in VS 2005, but not because they saw the compiler builds get slower, but simply because they saw the option was removed.
TBH the regular feedback we had was that the compiler was blazingly fast - particularly from folks who had been using C++ for a long while. This is another feature that, looking back, we probably should never have done.
It caused customers tons of headaches for little ultimate benefit. That said, I feel good about our willingness and decision to remove it. Occasionally, at Microsoft we fall prey to the sunk cost fallacy, but it's gotten much better over the years as our telemetry has
dramatically improved and we have lots of additional insight about usage and benefit versus what we had in 2003 when we made this decision. So, if anyone used VS 2002 and wondered what happened to this option, now you know :-)

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Anson Horton

Anson Horton Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @AnsonHorton

Dec 31, 2022
🧵Early in my career at Microsoft I was a PM on the C# compiler and language. Along with the QA and Dev lead we would regularly triage through bugs and decide when and whether they would be addressed. This was at a time when we'd spent the last 3 and 1/2 years working on VS 2002,
.NET 1.0, C# 1.0, etc. We were approaching our release and so our triage bar for fixing issues was very high, particularly in the compiler, as we tend to stabilize platform components earlier than leaf components. Microsoft had a system for entering and tracking bugs,
though I cannot remember if we were using Product Studio at that point or if it was still RAID. Regardless, they were similar in that they allowed resolving issues as 'postponed' if we decided we would address it in a future release.
Read 15 tweets
Sep 22, 2021
1/ The second 'feature' that the compiler team invested in during the VS 2003 release was ECMA conformance. The VS 2002 compiler was close; however, there were some areas that weren't yet covered. These were almost universally small things, but one is interesting because a lot of
2/ folks are still unaware this feature exists. C# supports two forms of XML doc comments, the extremely common single-line-doc-comment, and the much less used delimited-doc-comment. The delimited-doc-comment wasn't in the specification that Microsoft proposed to ECMA and was
3/ added later through the committee process. I cannot remember the who exactly pushed for this inclusion, but they were reasonably passionate about it, and I believe their rationale was familiarity with JavaDoc comment forms.
Read 10 tweets
Sep 21, 2021
1/ At the time that we shipped VS 2002, it was common to release several 'service packs' over the course of months or years afterwards. These service packs contained a large number of bug fixes that addressed issues that were discovered after we released. In comparison to today,
2/ the pace of releasing was glacial. I am much happier with the velocity at which we can ship updates now (though admittedly, I know some folks wish we didn't ship quite so often). Regardless, the next release after VS 2002 was originally intended to be a service pack. However,
3/ after some development, it became clear that the service pack was growing past simple bug fixes. Most notably, the release was set to align with the release of the .NET compact framework (anyone remember the codename for this? :-), and we wanted VS to have good support for
Read 14 tweets
Jun 26, 2021
1/ If you have ever worked with Windows Forms, you may have noticed that the icon that appears in solution explorer changes when it contains a 'designable' type, and that when you double-click on any file with that icon, it opens the designer.
2/ If you play around with this a bit, you may also notice that if you change a class to descend from System.Windows.Forms.Form, it will become designable, and the designer lights up. I doubt many people have thought about how that works.
3/ However, given the behavior, we can tell that somehow the project system must be able to detect when a class becomes designable… and how does it even know what it means to be designable anyway?
Read 13 tweets
Jun 25, 2021
1/ In the late 90s we were busy on the ambitious project of Visual Studio .NET, introducing a new runtime, new languages, and a new shell. The last involved combining several existing shells, VJ/VI/MSE 6, VC6, and VB6.
2/ This led to many difficult discussions, incredibly complicated and confounding technical challenges, and the most difficult problem - what side of the environment should the Solution Explorer dock to by default?
3/ In VC6, file view was on the left. In VJ/VI/MSE and VB6 the project explorer was on the right. You'd think that since you could move it, and that was persisted, it wouldn't matter that much.
Read 5 tweets
Jun 24, 2021
1/ In the VS 2005 release there were many new features for the C# IDE experience, several of which would generate code. An example was implement interface, which was proffered as either a 'smart tag' or through the context menu.
2/ Another was generate method stub, where we would optionally create a method if you consumed it without having declared it first. When we released VS 2005, these features would generate stubs of the following form (this is the code gen for implementing IComparable<Widget>):
3/ public int CompareTo(Widget other)
{
throw new Exception("The method or operation is not implemented.");
}

The C# community was, not surprisingly, somewhat confused (and often livid) that the code generation didn't use NotImplementedException instead.
Read 11 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us!

:(