Skip to content

Commit afb75a2

Browse files
authored
Improve perf of CredentialCache.GetCredential (#103714)
* Improve perf of CredentialCache.GetCredential * Minor changes
1 parent 3bcc947 commit afb75a2

File tree

1 file changed

+33
-18
lines changed

1 file changed

+33
-18
lines changed

src/libraries/Common/src/System/Net/CredentialCacheKey.cs

+33-18
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ internal CredentialCacheKey(Uri uriPrefix, string authenticationType)
2525
AuthenticationType = authenticationType;
2626
}
2727

28-
internal bool Match(Uri uri, string authenticationType)
28+
internal bool Match(Uri uri, int prefixLen, string authenticationType)
2929
{
3030
if (uri == null || authenticationType == null)
3131
{
@@ -40,12 +40,12 @@ internal bool Match(Uri uri, string authenticationType)
4040

4141
if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"Match({UriPrefix} & {uri})");
4242

43-
return IsPrefix(uri, UriPrefix);
43+
return IsPrefix(uri, prefixLen);
4444
}
4545

4646
// IsPrefix (Uri)
4747
//
48-
// Determines whether <prefixUri> is a prefix of this URI. A prefix
48+
// Determines whether <this> is a prefix of this URI. A prefix
4949
// match is defined as:
5050
//
5151
// scheme match
@@ -55,23 +55,22 @@ internal bool Match(Uri uri, string authenticationType)
5555
//
5656
// Returns:
5757
// True if <prefixUri> is a prefix of this URI
58-
private static bool IsPrefix(Uri uri, Uri prefixUri)
58+
private bool IsPrefix(Uri uri, int prefixLen)
5959
{
6060
Debug.Assert(uri != null);
61-
Debug.Assert(prefixUri != null);
61+
Uri uriPrefix = UriPrefix;
6262

63-
if (prefixUri.Scheme != uri.Scheme || prefixUri.Host != uri.Host || prefixUri.Port != uri.Port)
63+
if (uriPrefix.Scheme != uri.Scheme || uriPrefix.Host != uri.Host || uriPrefix.Port != uri.Port)
6464
{
6565
return false;
6666
}
6767

68-
int prefixLen = prefixUri.AbsolutePath.LastIndexOf('/');
69-
if (prefixLen > uri.AbsolutePath.LastIndexOf('/'))
68+
if (UriPrefixLength > prefixLen)
7069
{
7170
return false;
7271
}
7372

74-
return string.Compare(uri.AbsolutePath, 0, prefixUri.AbsolutePath, 0, prefixLen, StringComparison.OrdinalIgnoreCase) == 0;
73+
return string.Compare(uri.AbsolutePath, 0, uriPrefix.AbsolutePath, 0, UriPrefixLength, StringComparison.OrdinalIgnoreCase) == 0;
7574
}
7675

7776
public override int GetHashCode() =>
@@ -108,21 +107,37 @@ public static bool TryGetCredential(Dictionary<CredentialCacheKey, NetworkCreden
108107
mostSpecificMatch = null;
109108
mostSpecificMatchUri = null;
110109

111-
// Enumerate through every credential in the cache
110+
if (cache.Count == 0)
111+
{
112+
return false;
113+
}
114+
115+
// precompute the length of the prefix
116+
int uriPrefixLength = uriPrefix.AbsolutePath.LastIndexOf('/');
117+
118+
// Enumerate through every credential in the cache, get match with longest prefix
112119
foreach ((CredentialCacheKey key, NetworkCredential value) in cache)
113120
{
121+
int prefixLen = key.UriPrefixLength;
122+
123+
if (prefixLen <= longestMatchPrefix)
124+
{
125+
// this credential can't provide a longer prefix match
126+
continue;
127+
}
128+
114129
// Determine if this credential is applicable to the current Uri/AuthType
115-
if (key.Match(uriPrefix, authType))
130+
if (key.Match(uriPrefix, uriPrefixLength, authType))
116131
{
117-
int prefixLen = key.UriPrefixLength;
132+
// update the information about currently preferred match
133+
longestMatchPrefix = prefixLen;
134+
mostSpecificMatch = value;
135+
mostSpecificMatchUri = key.UriPrefix;
118136

119-
// Check if the match is better than the current-most-specific match
120-
if (prefixLen > longestMatchPrefix)
137+
if (uriPrefixLength == prefixLen)
121138
{
122-
// Yes: update the information about currently preferred match
123-
longestMatchPrefix = prefixLen;
124-
mostSpecificMatch = value;
125-
mostSpecificMatchUri = key.UriPrefix;
139+
// we can't get any better than this
140+
break;
126141
}
127142
}
128143
}

0 commit comments

Comments
 (0)