Showing content from https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/2204 below:
[Perf] Access tokens are listed too many times in AcquireTokenSilent
This issue impacts scenarios of large token cache, which is common for client credential flows (300k+ tokens). MSAL copies access tokens from memory into a list several times, which is a perf impact (TBD - numbers)
Technical details:
InMemoryTokenCacheAccessor.GetAllAccessTokens()
iterates through the whole AT collection and returns a List
. When TokenCacheNotificationArgs.HasTokens
property is set, it calls TokenCache.ITokenCacheInternal.HasTokensNoLocks()
which eventually calls InMemoryTokenCacheAccessor.GetAllAccessTokens()
. CacheSessionManager.RefreshCacheForReadOperationsAsync
sets that property twice.
So the AT dictionary ends up being iterated 3 times for a read, 2 times for a save. This can have a perf hit when cache has a large number of tokens.
Possible enhancement: Update GetAllAccessTokens()
to not create a list or reduce the number of calls to GetAllAccessTokens()
.
public IEnumerable<MsalAccessTokenCacheItem> GetAllAccessTokens() { // perf: do not call ConcurrentDictionary.Values as it takes a lock List<MsalAccessTokenCacheItem> ats = new List<MsalAccessTokenCacheItem>(); foreach (var kvp in _accessTokenCacheDictionary) { ats.Add(kvp.Value); } return ats; }
bool ITokenCacheInternal.HasTokensNoLocks() { return _accessor.GetAllRefreshTokens().Any() || _accessor.GetAllAccessTokens().Any(at => !IsAtExpired(at)); }
try { var args = new TokenCacheNotificationArgs( TokenCacheInternal, _requestParams.ClientId, _requestParams.Account, hasStateChanged: false, TokenCacheInternal.IsApplicationCache, hasTokens: TokenCacheInternal.HasTokensNoLocks(), suggestedCacheKey: key); await TokenCacheInternal.OnBeforeAccessAsync(args).ConfigureAwait(false); } finally { var args = new TokenCacheNotificationArgs( TokenCacheInternal, _requestParams.ClientId, _requestParams.Account, hasStateChanged: false, TokenCacheInternal.IsApplicationCache, hasTokens: TokenCacheInternal.HasTokensNoLocks(), suggestedCacheKey: key); await TokenCacheInternal.OnAfterAccessAsync(args).ConfigureAwait(false); }
RetroSearch is an open source project built by @garambo
| Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4