Skip to content

Watch directories for source files and some metadata references#42180

Merged
2 commits merged intodotnet:masterfrom
jasonmalinowski:switch-to-directory-watching
Jun 4, 2020
Merged

Watch directories for source files and some metadata references#42180
2 commits merged intodotnet:masterfrom
jasonmalinowski:switch-to-directory-watching

Conversation

@jasonmalinowski
Copy link
Member

@jasonmalinowski jasonmalinowski commented Mar 5, 2020

This is a performance improvement to avoid creating so many file watchers in Visual Studio. The Visual Studio file watching service consolidates file watchers to a single directory, but still has to manage the list of all of the file names we are trying to watch so it can appropriately filter, and the work to create all of that tracking is entirely unnecessary since in practice we're just going to watch all the files of a particular extension under a directory.

This is an optimization in that the FileChangeWatcher and does not impact correctness. When the FileChangeWatcher is asked to watch a file, it checks to see if the the file is under the directory and matches any extension filter; if not, it'll still create a regular file watch under the covers. This is opaque to the users, since they're getting file watches and will see change notifications either way. It's just a performance hint to avoid unnecessary work.

This required updating our mock implementation of the Visual Studio file change service to support requests for directory watching and for handling the filtering of them.

Fixes #13679
Fixes #42095

@jasonmalinowski jasonmalinowski requested a review from a team as a code owner March 5, 2020 00:40
@jasonmalinowski jasonmalinowski self-assigned this Mar 5, 2020
CyrusNajmabadi
CyrusNajmabadi previously approved these changes Mar 5, 2020
sharwell
sharwell previously approved these changes Mar 5, 2020
@jasonmalinowski
Copy link
Member Author

I've started a signed build so we can get an RPS run for this change.

jinujoseph
jinujoseph previously approved these changes Mar 5, 2020
@jasonmalinowski jasonmalinowski force-pushed the switch-to-directory-watching branch from a28a630 to ccbaa92 Compare March 5, 2020 18:41
@jasonmalinowski
Copy link
Member Author

Running a RPS run internally, this did hit one regression. Since we're watching the directory now, during Rebuild we're getting events that we weren't previously. It seems that there's a fair amount of allocation overhead from that in the file watching service on the order of 140 MB or so, which is almost enough to trip the regression flag. Will be sending an email to the owners of the service to see if there's some improvements we can make here.

@jasonmalinowski jasonmalinowski force-pushed the switch-to-directory-watching branch from ccbaa92 to c8cff54 Compare April 2, 2020 02:11
@jasonmalinowski jasonmalinowski modified the milestones: 16.6, 16.7 Apr 28, 2020
@jasonmalinowski jasonmalinowski changed the base branch from master to master-vs-deps May 20, 2020 23:02
@jasonmalinowski jasonmalinowski marked this pull request as draft May 20, 2020 23:02
@jasonmalinowski jasonmalinowski force-pushed the switch-to-directory-watching branch from c8cff54 to c7c304d Compare May 20, 2020 23:03
@jasonmalinowski
Copy link
Member Author

Switching this PR back to draft because right now it's using reflection as the VS platform team fixes a NuGet packaging issue with their packages. A new RPS run has been kicked off to investigate.

@jasonmalinowski jasonmalinowski force-pushed the switch-to-directory-watching branch from c7c304d to 30901c8 Compare June 3, 2020 02:03
@jasonmalinowski jasonmalinowski changed the base branch from master-vs-deps to master June 3, 2020 02:04
@jasonmalinowski jasonmalinowski changed the title Switch back to watching directories for source files Watch directories for source files and some metadata references Jun 3, 2020
@jasonmalinowski jasonmalinowski marked this pull request as ready for review June 3, 2020 02:04
@jasonmalinowski jasonmalinowski dismissed stale reviews from sharwell, CyrusNajmabadi, and jinujoseph June 3, 2020 02:05

Many code changes since last review.

@jasonmalinowski jasonmalinowski requested a review from a team June 3, 2020 02:05
Comment on lines 192 to 193
Copy link
Member Author

@jasonmalinowski jasonmalinowski Jun 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be fixed up in master-vs-deps; unfortunately we don't have 16.7 images yet (those come tomorrow) so there's no way it'd work until then.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't have 16.7 images yet (those come tomorrow)

I'm willing to wait until tomorrow for you to not use reflection.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have low confidence it'll work on the images we're getting since those were Preview 1 images and I think the API changes we needed went into Preview 2. Putting this in master and then removing the reflection in master-vs-deps is also helpful because it limits the code skew between the two branches.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

open tracking issue to get us off reflectio nhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just going to make the PR later today

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this work is async. i don't really understand the lifetimes of this async work, esp. wrt to unadvising.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We put all the actual calls to the service on a single queue, since the underlying VS service is more or less single threaded. Thus each operation here is added to a queue to be processed at a later time. The later unadvising still adds the operations to that queue.

What about the unadvising is confusing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. boy is that a terrifying comment. i'm going to presuem there's a big caveat of "because if someone else was accessing this concurrently, they'd be violating the disposal contract, and then all bets are off.
  2. would IAsyncDisposable be preferable here?

Copy link
Member Author

@jasonmalinowski jasonmalinowski Jun 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Yes, this is the standard "after dispose, it doesn't matter" case.
  2. I don't think so, since we wouldn't want it being awaited -- if I close a project there's no reason to block that action on our ability to stop watching files. That can happen later, or never in the case of an outright close of VS.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. worth doc'ing that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments updated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it gauranteed this folder exists? if it doesn't do we throw? or just silently go on?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only way it wouldn't exist is you don't have any .NET Framework SDK at all on the machine. If it didn't exist MiscellaneousFilesWorkspace would also be broken, because there'd be no references to pick up at all either for that.

@CyrusNajmabadi
Copy link
Contributor

I don't quite get the filtering. How it works or why we need it. Can you clarify?

Done with pass.

@jasonmalinowski
Copy link
Member Author

In our first attempt to do a single watch for all source files in the project, it improved memory usage and solution load/unload; the it hurt build time, and that was because by default the bin and obj folders are also under the project folder. When you built, all of the writing to temporary files there and the .dll or .exe was raising a bunch of extra change events. The VS layer has a bunch of overhead that once it knows somebody needs to be notified, it then creates a bunch of tasks and adds them to a queue for notification and certain synchronization. By knowing we don't even want those, it gave us an easy way to reduce that overhead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep as an expression-bodied-method?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meh. I can't say I care for them much beyond trivial accessors anyways. :-)

@CyrusNajmabadi
Copy link
Contributor

Do we have issues with things like editorconfig files or additional-files?

@jasonmalinowski
Copy link
Member Author

@CyrusNajmabadi We shouldn't. These directory watches are purely as an optimization; anything not matched in the directory watch (either it's outside the directory, or the extension doesn't match) still gets an explicit file watch added so we'll still pick it up.

@jasonmalinowski jasonmalinowski force-pushed the switch-to-directory-watching branch from 30901c8 to 504c226 Compare June 3, 2020 19:33
@CyrusNajmabadi
Copy link
Contributor

Got it. do you think that's documented well enough for the future?

@jasonmalinowski
Copy link
Member Author

@CyrusNajmabadi I clarified a bit more in the PR message but I think we're OK.

This is a performance improvement to avoid creating so many file
watchers in Visual Studio. The Visual Studio file watching service
consolidates file watchers to a single directory, but still has to
manage the list of all of the file names we are trying to watch so it
can appropriately filter, and the work to create all of that tracking
is entirely unnecessary since in practice we're just going to watch
all the files of a particular extension under a directory.

This is an optimization in that the FileChangeWatcher and does not
impact correctness. When the FileChangeWatcher is asked to watch a file,
it checks to see if the the file is under the directory and matches any
extension filter; if not, it'll still create a regular file watch under
the covers. This is opaque to the users, since they're getting file
watches and will see change notifications either way. It's just a
performance hint to avoid unnecessary work.

This required updating our mock implementation of the Visual Studio
file change service to support requests for directory watching and for
handling the filtering of them.

Fixes dotnet#13679
Fixes dotnet#42095
@jasonmalinowski jasonmalinowski force-pushed the switch-to-directory-watching branch from 504c226 to 0bb2853 Compare June 3, 2020 21:21
Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-approval

@ghost ghost merged commit a9fb862 into dotnet:master Jun 4, 2020
@jasonmalinowski jasonmalinowski deleted the switch-to-directory-watching branch June 5, 2020 00:13
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create a single file watcher for a folder The Visual Studio workspace should consume the new file watching APIs

5 participants