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) {
|
public TResult Get(TKey key, Func<AcquireContext<TKey>, TResult> acquire) {
|
||||||
var entry = _entries.AddOrUpdate(key,
|
var entry = _entries.AddOrUpdate(key,
|
||||||
// "Add" lambda
|
// "Add" lambda
|
||||||
k => CreateEntry(k, acquire),
|
k => AddEntry(k, acquire),
|
||||||
// "Update" lamdba
|
// "Update" lamdba
|
||||||
(k, currentEntry) => (currentEntry.GetTokens() != null && currentEntry.GetTokens().Any(t => !t.IsCurrent) ? CreateEntry(k, acquire) : currentEntry));
|
(k, currentEntry) => UpdateEntry(currentEntry, k, acquire));
|
||||||
|
|
||||||
// Bubble up volatile tokens to parent context
|
|
||||||
if (_cacheContextAccessor.Current != null && entry.GetTokens() != null) {
|
|
||||||
foreach (var token in entry.GetTokens())
|
|
||||||
_cacheContextAccessor.Current.Monitor(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry.Result;
|
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) {
|
private CacheEntry CreateEntry(TKey k, Func<AcquireContext<TKey>, TResult> acquire) {
|
||||||
var entry = new CacheEntry();
|
var entry = new CacheEntry();
|
||||||
@@ -46,23 +60,31 @@ namespace Orchard.Caching {
|
|||||||
// Pop context
|
// Pop context
|
||||||
_cacheContextAccessor.Current = parentContext;
|
_cacheContextAccessor.Current = parentContext;
|
||||||
}
|
}
|
||||||
|
entry.CompactTokens();
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CacheEntry {
|
private class CacheEntry {
|
||||||
|
private IList<IVolatileToken> _tokens;
|
||||||
public TResult Result { get; set; }
|
public TResult Result { get; set; }
|
||||||
private IList<IVolatileToken> Tokens { get; set; }
|
|
||||||
|
|
||||||
public void AddToken(IVolatileToken volatileToken) {
|
public IEnumerable<IVolatileToken> Tokens {
|
||||||
if (Tokens == null) {
|
get {
|
||||||
Tokens = new List<IVolatileToken>();
|
return _tokens ?? Enumerable.Empty<IVolatileToken>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Tokens.Add(volatileToken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<IVolatileToken> GetTokens() {
|
public void AddToken(IVolatileToken volatileToken) {
|
||||||
return Tokens;
|
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