mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
PERF: Compact list of tokens for cache entries
Due to the way we nest cache context implicitly, there were cases where we had 1,500+ tokens with only 200+ unique ones. We now call "distinct" on the tokens when after an entry is created. This decreases memory usage and also improve performance on cache hits (fewer tokens to go though each time). --HG-- branch : 1.x
This commit is contained in:
@@ -16,19 +16,33 @@ namespace Orchard.Caching {
|
||||
public TResult Get(TKey key, Func<AcquireContext<TKey>, TResult> acquire) {
|
||||
var entry = _entries.AddOrUpdate(key,
|
||||
// "Add" lambda
|
||||
k => CreateEntry(k, acquire),
|
||||
k => AddEntry(k, acquire),
|
||||
// "Update" lamdba
|
||||
(k, currentEntry) => (currentEntry.GetTokens() != null && currentEntry.GetTokens().Any(t => !t.IsCurrent) ? CreateEntry(k, acquire) : currentEntry));
|
||||
|
||||
// Bubble up volatile tokens to parent context
|
||||
if (_cacheContextAccessor.Current != null && entry.GetTokens() != null) {
|
||||
foreach (var token in entry.GetTokens())
|
||||
_cacheContextAccessor.Current.Monitor(token);
|
||||
}
|
||||
(k, currentEntry) => UpdateEntry(currentEntry, k, acquire));
|
||||
|
||||
return entry.Result;
|
||||
}
|
||||
|
||||
private CacheEntry AddEntry(TKey k, Func<AcquireContext<TKey>, TResult> acquire) {
|
||||
var entry = CreateEntry(k, acquire);
|
||||
PropagateTokens(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
private CacheEntry UpdateEntry(CacheEntry currentEntry, TKey k, Func<AcquireContext<TKey>, TResult> acquire) {
|
||||
var entry = (currentEntry.Tokens.Any(t => !t.IsCurrent)) ? CreateEntry(k, acquire) : currentEntry;
|
||||
PropagateTokens(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
private void PropagateTokens(CacheEntry entry) {
|
||||
// Bubble up volatile tokens to parent context
|
||||
if (_cacheContextAccessor.Current != null) {
|
||||
foreach (var token in entry.Tokens)
|
||||
_cacheContextAccessor.Current.Monitor(token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private CacheEntry CreateEntry(TKey k, Func<AcquireContext<TKey>, TResult> acquire) {
|
||||
var entry = new CacheEntry();
|
||||
@@ -46,23 +60,31 @@ namespace Orchard.Caching {
|
||||
// Pop context
|
||||
_cacheContextAccessor.Current = parentContext;
|
||||
}
|
||||
entry.CompactTokens();
|
||||
return entry;
|
||||
}
|
||||
|
||||
private class CacheEntry {
|
||||
private IList<IVolatileToken> _tokens;
|
||||
public TResult Result { get; set; }
|
||||
private IList<IVolatileToken> Tokens { get; set; }
|
||||
|
||||
public void AddToken(IVolatileToken volatileToken) {
|
||||
if (Tokens == null) {
|
||||
Tokens = new List<IVolatileToken>();
|
||||
public IEnumerable<IVolatileToken> Tokens {
|
||||
get {
|
||||
return _tokens ?? Enumerable.Empty<IVolatileToken>();
|
||||
}
|
||||
|
||||
Tokens.Add(volatileToken);
|
||||
}
|
||||
|
||||
public IEnumerable<IVolatileToken> GetTokens() {
|
||||
return Tokens;
|
||||
public void AddToken(IVolatileToken volatileToken) {
|
||||
if (_tokens == null) {
|
||||
_tokens = new List<IVolatileToken>();
|
||||
}
|
||||
|
||||
_tokens.Add(volatileToken);
|
||||
}
|
||||
|
||||
public void CompactTokens() {
|
||||
if (_tokens != null)
|
||||
_tokens = _tokens.Distinct().ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user