-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
Summary
When the Roslyn Language Server runs on Linux, .NET's FileSystemWatcher creates an inotify watch for every subdirectory under each watched path — because Linux's inotify API has no native recursive watch support. Since Roslyn watches ~/.nuget/packages (among other paths) for reference DLL changes, this results in hundreds of thousands of inotify registrations. This exhausts the system's inotify limit and causes VS Code to report constant "unable to watch" warnings across the entire editor.
Note - this is specifically hitting the watch limit, not the instance limit.
Details
The watch on ~/.nuget/packages is registered in FileWatchedReferenceFactory.GetAdditionalWatchedDirectories() to detect changes to referenced DLLs. On Windows, ReadDirectoryChangesW handles recursive watching natively with one OS handle. On Linux, .NET's FileSystemWatcher must create a separate inotify file descriptor for every subdirectory, and the NuGet cache contains thousands of packages with deep directory trees that grow over time as new versions accumulate.
The code already skips this watch on Windows (line 105-108) due to concerns about overhead during restore.
Observed scale (Fred's machine)
- ~308,000 directory watches in
~/.nuget/packages - ~470,000 total watches from the LSP process
- Top packages by watch count:
microsoft.codeanalysis.common(5,766),microsoft.codeanalysis.workspaces.common(5,368),microsoft.codeanalysis.csharp(5,194) - The NuGet cache contained 60+ versions of some packages (e.g.
microsoft.codeanalysis.common)
Suggestions from discussion
-
Consolidate watched directories with a cap: Maintain a list of watched directories with a maximum count (e.g. 10). When adding a new watch, check if it's already contained by an existing directory watcher. If not, check if it contains any existing watches and consolidate. Start the list seeded with the home directory. When too many leaf watches accumulate, consolidate upward to a common ancestor. This bounds inotify usage regardless of how many paths Roslyn needs to observe.
-
Wait for .NET 11 improvements: FileSystemWatching on non-Windows is expected to improve in .NET 11, but the Roslyn LSP runs as a dotnet tool and likely needs to target LTS versions, so this isn't a near-term solution.