[MUSIC]
>> Hi, I'm Sam Hartwell.
I'm a member of the.NET Developer
experience team here at Microsoft,
and in addition to working on the C# and
Visual Basic IDE experiences,
our team is heavily focused on inner loop developer productivity.
As part of this, we're frequently asked to help teams and
other divisions around Microsoft when
their developer tools seem slow.
Over time, we've seen some common patterns emerge with
simple solutions that greatly improved their experiences.
By sharing this knowledge,
we're hoping you'll be able to see similar benefits.
Our goal today is to show some of
our expectations for IDE performance
so that you can better identify
problematic scenarios and resolve
them to maximize your team productivity.
>> Hi. My name is Drew Noakes and I'm an Engineer on
the.NET and Visual Studio teams here at Microsoft.
Lately, I've been focusing on improving
the performance of builds across Visual Studio,
and we have a bunch of performance improvements
coming in Visual Studio 2022,
which will help make you more productive.
While we do everything we can to make builds faster by default,
there may still be things you can do to
improve the performance of your builds.
Today, we're talking specifically about incremental builds,
so let's explore what that is.
We'll do that in this solution,
we have a very simple solution here,
just has two projects.
You can see there's a "Console Application" and a "Class
Library," and the "Console Application"
has a reference to the "Class Library."
Let's do the first build.
This is not an incremental build,
this as a full build.
Nothing has been built before.
We see that everything completed and it took about a second.
We can see that there were two projects that were built,
there were no errors,
and nothing was up to date.
Now, if we build again, we would expect what we've built
previously to kick-in and
everything to be up to date, so let's check that.
Indeed, we see the two projects were up to date.
That is the essence of incremental build.
Nothing has changed, so there was nothing to build.
The increment is,
you can think of it as the part that you change and it
will build just that part and avoid doing that redundant work.
You can see in this case, there was nothing to do beyond
working out that we were up to date and that was quite quick.
Took about 30 milliseconds.
You see we run it again a few times,
it continues to be very fast.
That's incremental build when it's working well.
Makes you much more productive and it's worth
noting that these build times don't happen just
when you right-click "Build Your
Project," but it also happened whenever
you launch into the debugger
or whenever you're running a unit test.
Builds are a common task that you perform,
and sitting around waiting for a build to
complete is never a right use of time.
>> Here, we have another solution,
it also has two projects and it's structured very
similar to the first solution that we just looked at.
You'll notice that in this solution,
if you try to follow the original steps
of you build the first time,
you see that it built two projects again,
two succeeded, no fail,
and none were up to date,
and the build time was about the same as what we saw
before taking one second.
However, for this solution,
if I was to do the same thing again without making any changes,
instead of seeing the 20 millisecond quick up to date,
I noticed that it still takes almost three quarters of a second.
One project is saying succeeded and one is saying up to date.
This isn't an error condition.
Everything is building successfully,
but it's not behaving with the performance level that
we expected for an incremental build where nothing changed.
To figure out why this one solution
built this time and if I was to right-click and build solution,
you'll see it happens again.
We need to go and figure out why Visual Studio did not think
this solution was up to
date when I ran that second and third build.
To do this, in "Tools,"
"Options" under "Projects and Solutions" and
"SDK Style Projects," there's
a logging level related to the up-to-date check.
If I change that from the default value of none over to minimal,
each build is going to have an extra line
explaining the reason why the build
started instead of being considered up to date.
For this solution, this line,
the fast up-to-date check says a file,
this in particular,
data.json has copy to output directory set to copy always.
Therefore, the solution in
this particular project is considered never up to date.
This is a fairly common situation
that teams have accidentally gotten themselves into,
and the solution is quite simple.
If you find the offending file,
in our case data.json,
and open the "Properties Window," I can see
that copy to output directory is set to copy always.
By changing this to copy if newer,
the build will still run each time I change this file.
However, if I build the solution the first time,
it says the solution had to change
and the change was I set the value to copy if newer.
However, subsequent builds where I don't make
any changes to the properties or to the content of any of
the files are now considered immediately up to
date and we're back to the 20 millisecond
builds that the first example had.
By changing the value to copy if newer instead of copy always,
I didn't lose the ability to make a change
to this JSON file and then build
the solution and see that it did rebuild the project in question.
However, each time you
build without making any changes to that file,
you're back to the 20 millisecond build times.
>> Thanks, Sam. Let's look at another example now.
Just little harder to diagnose but will help us to
show another scenario
that incremental build problems can surface in.
Here, we have a very similar project
and although we don't have a data.json file anymore,
what we now have is this package reference
and we're referencing this shouldly library.
You'll see that when we build,
the first time, two succeeded,
as we would expect.
When we build another time now,
we've seen that incremental build
did not happen at actual build occurred.
Let's have a look at the error message and see if it helps us.
This time, it's not talking about any file in our project,
it's talking about some debug symbols, this PDB file.
That's a little bit less clear what's going on.
It's saying that some file does not exist, but actually,
the debugging of this was a bit more
involved and it required some additional tools,
something called the "MSBuild Structured Log Viewer"
was very valuable here.
We'll skip the exact details of the issue and just talk about
the symptoms and how to fix it in this particular instance.
So here, you see we're using the shouldly library.
MSBuild is a very customizable platform
and it's possible for package references,
you get packages to include files that modify your build.
In this particular instance,
shouldly version 4.0.1,
perform some build customization that
broke incremental builds for that project.
Now, in version 4.0.3,
that issue has been resolved,
so if we save that,
upgrade to the new version of the package, you've made a change,
so building will actually cause a build,
and if we build again, now we see we are back up to date.
This really highlights that sometimes,
these issues are things that you might have
direct control over in your project file,
but they may also come from other sources
>> Thanks, Drew. I know these scenarios
are very complicated and there's
a whole bunch of different reasons why things
could end up impacting build performance.
We've included some resources in the description below,
some of these are tools that we use here at
Microsoft to diagnose the problems that other teams are facing.
We also have included some links to
our reporter problem tool which will allow you
to reach out to us if you're not
able to resolve these and you're seeing
performance that doesn't match
what you want to see at your company.
Finally, if you're a team member that works on
build performance that affects
a large number of other developers,
I would encourage you to reach out and make
sure that other people on the team are
seeing the same improvements that
you're seeing for improvements that are made.
We've seen some cases where
an individual user settings led
to their builds being slower than the rest of the team,
and anytime that you let a situation like that go on for awhile,
that team member could end up being less productive even though
a simple change of settings to
be consistent would improve it for them.
Also remember that builds,
they're a very resource intensive process,
so if the steps previously aren't working for you,
you may find that improving
the hardware that you're working with
could have a pretty big impact.
In particular, builds benefit from SSD storage,
both for the operating system
and for the drive containing the project you're working on.