-
Notifications
You must be signed in to change notification settings - Fork 269
Description
Problem Statement
Today, NuGet has no consistent story about the number of parallel HTTP requests allowed.
In our Visual Studio extension, I am not aware of any HTTP request throttling. We probably end up using whatever ServicePointManager.DefaultConnectionLimit is set to. In fact, it's possible VS or some other component sets this value. Needs investigation.
I am investigating a user report where their restore in Visual Studio times out. This is a graph of the number of pending HTTP requests that NuGet restore makes. The Y axis is the number pending requests. The X axis is 1 unit per output log line.
It's not surprised that things start timing out when over 200 HTTP requests are in flight at the same time.
Workaround
nuget.exe and dotnet restore have -DisableParallel and --disable-parallel options, respectively, which set the maximum number of parallel HTTP calls down to 1. This is good for debugging but in practice is very slow.
If the restore is never completing in Visual Studio, use dotnet restore --disable-parallel or nuget.exe restore -DisableParallel from the command line to get one successful restore. Then, subsequent restores in Visual Studio should require many fewer HTTP requests, since all of the packages are already downloaded.
Current Code
We have a NetworkProtocolUtility.SetConnectionLimit API, but this only works on .NET Framework and sets the value to 64 on non-Mono environments (Mono is set to 1). This API is not called in VS (and should not until we know how it would effect other components in the VS process and if it's even the right solution).
HttpSource has an IThrottle parameter which allows controlling the total number of pending HTTP requests. This is used for --disable-parallel by implementing IThrottle with a semaphore of size 1.
Package.config use maxDegreeOfParallelism which is set to Environment.ProcessorCount by default for dependency fetching and package download & extraction
PackageReference throttling in SourceRepositoryDependencyProvider only on mac for dependency resolving and use MaxDegreeOfConcurrency for package download and extraction. The default value for both are 16
Suggested Implementation
We should throttle the number of concurrent HTTP requests that NuGet makes. We should set a sane default and allow configuration in NuGet.config. Our goal should be that most users shouldn't have to care about this configuration value because it will provide a good balance of performance and stability.
We should also determine whether there should be throttling at a source-level (e.g. up to 8 parallel HTTP requests against nuget.org, not effecting the count against myget.org). This models ServicePointManager.DefaultConnectionLimit which is on a per remote host basis.
Spec: https://github.com/NuGet/Home/wiki/Config-Max-Http-Request-In-NuGet
