Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 712d306

Browse files
authored
Optimize proxy PAC file discovery process for SocketsHttpHandler (#29050)
This PR will reduce the calls to WinHTTP GetProxyForUrl() if a previous call recently discovered no PAC file within a certain timeframe. We call this API when "Automatically detect settings" is turned on. The default configuration on Windows has this proxy setting always turned on. This is ironic given that most network environments don't have a PAC file on the network. So, it's important to try to optimize this common case on customers' networks. Initial testing shows at least a 2x speed improvement with these changes. I did not use any locking mechanisms since those would drag down performance. In the worst case, any race condition would mean we might call GetProxyForUrl() an extra time. But since we're only filtering on ERROR_WINHTTP_AUTODETECTION_FAILED, it is unlikely to actually change over time. That particular error means that the WPAD protocol was able to complete on the network, but the answer discovered is that there is no PAC file registered on the network. Fixes #28543
1 parent 9964306 commit 712d306

File tree

2 files changed

+30
-11
lines changed

2 files changed

+30
-11
lines changed

src/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinInetProxyHelper.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ namespace System.Net.Http
1414
internal class WinInetProxyHelper
1515
{
1616
private bool _useProxy = false;
17+
private bool _autoDetectionFailed;
18+
private int _lastTimeAutoDetectionFailed; // Environment.TickCount units (milliseconds).
19+
private const int _recentAutoDetectionInterval = 120_000; // 2 minutes in milliseconds.
1720

1821
public WinInetProxyHelper()
1922
{
@@ -79,6 +82,10 @@ public bool ManualSettingsOnly
7982

8083
public string ProxyBypass { get; set; }
8184

85+
public bool RecentAutoDetectionFailure =>
86+
_autoDetectionFailed &&
87+
Environment.TickCount - _lastTimeAutoDetectionFailed <= _recentAutoDetectionInterval;
88+
8289
public bool GetProxyForUrl(
8390
SafeWinHttpHandle sessionHandle,
8491
Uri uri,
@@ -123,6 +130,7 @@ public bool GetProxyForUrl(
123130
var repeat = false;
124131
do
125132
{
133+
_autoDetectionFailed = false;
126134
if (Interop.WinHttp.WinHttpGetProxyForUrl(
127135
sessionHandle,
128136
uri.AbsoluteUri,
@@ -131,7 +139,7 @@ public bool GetProxyForUrl(
131139
{
132140
WinHttpTraceHelper.Trace("WinInetProxyHelper.GetProxyForUrl: Using autoconfig proxy settings");
133141
useProxy = true;
134-
142+
135143
break;
136144
}
137145
else
@@ -154,6 +162,12 @@ public bool GetProxyForUrl(
154162
}
155163
else
156164
{
165+
if (lastError == Interop.WinHttp.ERROR_WINHTTP_AUTODETECTION_FAILED)
166+
{
167+
_autoDetectionFailed = true;
168+
_lastTimeAutoDetectionFailed = Environment.TickCount;
169+
}
170+
157171
break;
158172
}
159173
}

src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpSystemProxy.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -326,20 +326,25 @@ public Uri GetProxy(Uri uri)
326326
return (uri.Scheme == UriScheme.Https || uri.Scheme == UriScheme.Wss) ? _secureProxyUri : _insecureProxyUri;
327327
}
328328

329-
// For anything else ask WinHTTP.
330-
var proxyInfo = new Interop.WinHttp.WINHTTP_PROXY_INFO();
331-
try
329+
// For anything else ask WinHTTP. To improve performance, we don't call into
330+
// WinHTTP if there was a recent failure to detect a PAC file on the network.
331+
if (!_proxyHelper.RecentAutoDetectionFailure)
332332
{
333-
if (_proxyHelper.GetProxyForUrl(_sessionHandle, uri, out proxyInfo))
333+
var proxyInfo = new Interop.WinHttp.WINHTTP_PROXY_INFO();
334+
try
334335
{
335-
return GetUriFromString(Marshal.PtrToStringUni(proxyInfo.Proxy));
336+
if (_proxyHelper.GetProxyForUrl(_sessionHandle, uri, out proxyInfo))
337+
{
338+
return GetUriFromString(Marshal.PtrToStringUni(proxyInfo.Proxy));
339+
}
340+
}
341+
finally
342+
{
343+
Marshal.FreeHGlobal(proxyInfo.Proxy);
344+
Marshal.FreeHGlobal(proxyInfo.ProxyBypass);
336345
}
337346
}
338-
finally
339-
{
340-
Marshal.FreeHGlobal(proxyInfo.Proxy);
341-
Marshal.FreeHGlobal(proxyInfo.ProxyBypass);
342-
}
347+
343348
return null;
344349
}
345350

0 commit comments

Comments
 (0)