Skip to content

Commit

Permalink
Improve perf of CredentialCache.GetCredential (#103714)
Browse files Browse the repository at this point in the history
* Improve perf of CredentialCache.GetCredential

* Minor changes
  • Loading branch information
rzikm committed Jun 25, 2024
1 parent 3bcc947 commit afb75a2
Showing 1 changed file with 33 additions and 18 deletions.
51 changes: 33 additions & 18 deletions src/libraries/Common/src/System/Net/CredentialCacheKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal CredentialCacheKey(Uri uriPrefix, string authenticationType)
AuthenticationType = authenticationType;
}

internal bool Match(Uri uri, string authenticationType)
internal bool Match(Uri uri, int prefixLen, string authenticationType)
{
if (uri == null || authenticationType == null)
{
Expand All @@ -40,12 +40,12 @@ internal bool Match(Uri uri, string authenticationType)

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

return IsPrefix(uri, UriPrefix);
return IsPrefix(uri, prefixLen);
}

// IsPrefix (Uri)
//
// Determines whether <prefixUri> is a prefix of this URI. A prefix
// Determines whether <this> is a prefix of this URI. A prefix
// match is defined as:
//
// scheme match
Expand All @@ -55,23 +55,22 @@ internal bool Match(Uri uri, string authenticationType)
//
// Returns:
// True if <prefixUri> is a prefix of this URI
private static bool IsPrefix(Uri uri, Uri prefixUri)
private bool IsPrefix(Uri uri, int prefixLen)
{
Debug.Assert(uri != null);
Debug.Assert(prefixUri != null);
Uri uriPrefix = UriPrefix;

if (prefixUri.Scheme != uri.Scheme || prefixUri.Host != uri.Host || prefixUri.Port != uri.Port)
if (uriPrefix.Scheme != uri.Scheme || uriPrefix.Host != uri.Host || uriPrefix.Port != uri.Port)
{
return false;
}

int prefixLen = prefixUri.AbsolutePath.LastIndexOf('/');
if (prefixLen > uri.AbsolutePath.LastIndexOf('/'))
if (UriPrefixLength > prefixLen)
{
return false;
}

return string.Compare(uri.AbsolutePath, 0, prefixUri.AbsolutePath, 0, prefixLen, StringComparison.OrdinalIgnoreCase) == 0;
return string.Compare(uri.AbsolutePath, 0, uriPrefix.AbsolutePath, 0, UriPrefixLength, StringComparison.OrdinalIgnoreCase) == 0;
}

public override int GetHashCode() =>
Expand Down Expand Up @@ -108,21 +107,37 @@ public static bool TryGetCredential(Dictionary<CredentialCacheKey, NetworkCreden
mostSpecificMatch = null;
mostSpecificMatchUri = null;

// Enumerate through every credential in the cache
if (cache.Count == 0)
{
return false;
}

// precompute the length of the prefix
int uriPrefixLength = uriPrefix.AbsolutePath.LastIndexOf('/');

// Enumerate through every credential in the cache, get match with longest prefix
foreach ((CredentialCacheKey key, NetworkCredential value) in cache)
{
int prefixLen = key.UriPrefixLength;

if (prefixLen <= longestMatchPrefix)
{
// this credential can't provide a longer prefix match
continue;
}

// Determine if this credential is applicable to the current Uri/AuthType
if (key.Match(uriPrefix, authType))
if (key.Match(uriPrefix, uriPrefixLength, authType))
{
int prefixLen = key.UriPrefixLength;
// update the information about currently preferred match
longestMatchPrefix = prefixLen;
mostSpecificMatch = value;
mostSpecificMatchUri = key.UriPrefix;

// Check if the match is better than the current-most-specific match
if (prefixLen > longestMatchPrefix)
if (uriPrefixLength == prefixLen)
{
// Yes: update the information about currently preferred match
longestMatchPrefix = prefixLen;
mostSpecificMatch = value;
mostSpecificMatchUri = key.UriPrefix;
// we can't get any better than this
break;
}
}
}
Expand Down

0 comments on commit afb75a2

Please sign in to comment.