Jon*_*Rea 7 c# collections asp.net-mvc multithreading lru
这可能就像在棍子上求月亮一样;但是是否有“C# 生产质量线程安全的内存中 LRU 缓存与到期?或者有没有人有最佳实践的想法来实现同样的事情?
(LRU 是“最近最少使用” - http://en.wikipedia.org/wiki/Cache_algorithms#LRU)
澄清一下:我想在具有以下接口的 ASP.Net MVC 站点中支持内存缓存:
public interface ICache
{
T GetOrAdd<T>(string key, Func<T> create, TimeSpan timeToLive) where T : class;
bool Remove(string key);
}
Run Code Online (Sandbox Code Playgroud)
Microsoft 的最佳解决方案似乎是“System.Runtime.Caching.MemoryCache”,但它似乎有几个警告:
代码如下所示:
public sealed class Cache : ICache
{
private readonly MemoryCache _cache;
public Cache()
{
_cache = MemoryCache.Default;
}
public T GetOrAdd<T>(string key, Func<T> create, TimeSpan timeToLive) where T : class
{
// This call kinda defeats the point of the cache ?!?
var newValue = create();
return _cache.AddOrGetExisting(key, newValue, DateTimeOffset.UtcNow + timeToLive) as T;
}
public bool Remove(string key)
{
_cache.Remove(key);
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
或者也许在 Lazy < T > 周围有更好的东西,它确实允许只创建一次结果,但感觉就像一个黑客(缓存 Func 有什么后果?):
class Program
{
static void Main(string[] args)
{
Func<Foo> creation = () =>
{
// Some expensive thing
return new Foo();
};
Cache cache = new Cache();
// Result 1 and 2 are correctly the same instance. Result 3 is correctly a new instance...
var result1 = cache.GetOrAdd("myKey", creation, TimeSpan.FromMinutes(30));
var result2 = cache.GetOrAdd("myKey", creation, TimeSpan.FromMinutes(30));
var result3 = cache.GetOrAdd("myKey3", creation, TimeSpan.FromMinutes(30));
return;
}
}
public sealed class Foo
{
private static int Counter = 0;
private int Index = 0;
public Foo()
{
Index = ++Counter;
}
}
public sealed class Cache
{
private readonly MemoryCache _cache;
public Cache()
{
_cache = MemoryCache.Default;
}
public T GetOrAdd<T>(string key, Func<T> create, TimeSpan timeToLive) where T : class
{
var newValue = new Lazy<T>(create, LazyThreadSafetyMode.PublicationOnly);
var value = (Lazy<T>)_cache.AddOrGetExisting(key, newValue, DateTimeOffset.UtcNow + timeToLive);
return (value ?? newValue).Value;
}
public bool Remove(string key)
{
_cache.Remove(key);
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
其他想法:
我实现了一个专为并发工作负载设计的线程安全伪 LRU - 目前在生产系统中使用。性能非常接近 ConcurrentDictionary,比 MemoryCache 快 10 倍,命中率比传统 LRU 好。下面的github链接中提供了完整的分析。
用法如下所示:
int capacity = 666;
var lru = new ConcurrentTLru<int, SomeItem>(capacity, TimeSpan.FromMinutes(5));
var value = lru.GetOrAdd(1, (k) => new SomeItem(k));
bool removed = lru.TryRemove(1);
Run Code Online (Sandbox Code Playgroud)
GitHub: https://github.com/bitfaster/BitFaster.Caching
Install-Package BitFaster.Caching
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2159 次 |
| 最近记录: |