我正在编写一些使用反射的代码。所以我试图将昂贵的反射处理缓存到ConcurrentDictionary
。但是,我想对并发字典应用限制限制,以防止存储旧的和未使用的缓存值。
我做了一些研究,看看如何限制ConcurrentDictionary
的大小。我找到了一些有趣的答案,但是我不知道答案是否符合我的要求并且表现良好。
我在Dapper源代码中发现他们做了一些自定义代码来处理ConcurrentDictionary
的限制。它们具有与Interlocked一起使用的集合限制常量,以便能够处理字典的并发性。
另一方面,我在SO上发现answer,它使用普通的Dictionary,然后在其上应用ReaderWriterLockSlim
来处理并发。我不知道它是否与.Net源代码中的实现相同。
我应该使用dapper实现还是SO答案实现?
答案 0 :(得分:2)
出于性能考虑,您根本不应使用锁定。另外,请注意ConcurrentDictionary
类中隐藏的性能瓶颈,例如枚举集合时会创建垃圾(请参阅问题here)。
反射缓存的唯一明智的解决方案是为每个线程有一个单独的字典。是的,这会花费一些RAM,但是性能会更好。
public static class TypeExtensions
{
[ThreadStatic] private static Dictionary<Type, PropertyInfo> propertyInfoLookup;
private static Dictionary<Type, PropertyInfo> MemberInfoLookup =>
propertyInfoLookup ??= new Dictionary<Type, PropertyInfo>();
// Sample API
public static PropertyInfo GetPropertyInfo(this Type type) => MemberInfoLookup[type];
}
答案 1 :(得分:0)
准确的方式&#34;缓存信息&#34;在环境方面有很多变化。像WebDevelopment这样的领域需要采用完全不同的方法,这要归功于环境的高度分离性和高水平的分离。
但是,缓存任何东西的核心是WeakReference。强引用阻止了GC的收集。 WeakReferences不会,但允许您获得强引用。这是程序员说的方式&#34;不要仅仅为了这个列表而将它保存在内存中。但是如果你还没有收集它,请给我一个强有力的参考。&#34;:
https://msdn.microsoft.com/en-us/library/system.weakreference.aspx
就其本质而言,当所有其他线程暂停时,GC只能收集(或标记该主要的弱引用)。所以WeakReferences不应该让你接触到更多的竞争条件 - 它仍然存在,你现在有一个强大的参考,或者它没有。