在我的ASP.NET应用程序中,我有一个包含大量对象的字典(比如说大到1M,之后可能会变大),存储在字典中的对象是引用类型而不是struct类型,字典意味着作为这种类型对象的缓存(我有理由不使用ASP.NET缓存来缓存这种类型的对象,我用它来缓存其他东西)。
这会导致GC出现问题吗?我一直听说长寿命物体会影响GC的性能并导致它在收集过程中花费更多时间,是否有避免这种情况?据我所知,字典(和对象)最终应该在Gen2中,除非系统内存不足,否则GC不会收集它(如果我错了请纠正我),那么如果系统有很多内容呢?记忆,GC仍会以相同的频率收集Gen2吗?必须有其他应用程序长时间缓存大量数据,我想知道它们如何避免GC的问题。
任何建议都非常感谢......
答案 0 :(得分:3)
在大约1M条目中,基础数组的字典将不可避免地最终出现在LOH中。鉴于此,最好将其预分配的大小与其最终包含的条目数相当(这可能会严重反击,并且可能是测试模式中的一种痛苦)。
字典中的对象应该提供非常好的哈希码实现。这与内存使用无直接关系,只与查找效率有关。但是,如果您为较少的内存使用交换较高的加载因子,则错误的哈希最终可能会使字典行为降级到不再是O(1)的程度。
它包含的长寿命项目应该是:
(最佳情况)不包含作为引用类型的实例字段。
确保您的应用程序不会进入Mid Life Crisis样式行为
它们包含的任何引用都不应指向Gen0或Gen1堆
由于您声明这是一个缓存但未提及您的保留政策,我认为此advice也值得一提。
你正在缓存的对象类型的一些指示可能是相关的4 / 8MB或连续内存是非常多的,即使使用现代处理器缓存,因此对缓存的频繁请求可能比具有更紧密,更小的缓存更糟糕的性能更好的保留政策。
答案 1 :(得分:1)
你理解这个场景是正确的,只要系统不渴望内存Gen2集合应该是不常见的,因此在那里保留许多长寿命对象应该不是问题。
如果您必须仔细编码以避免GC出现“问题”,GC将无法很好地完成其工作。
真正需要关注的唯一区域是大量分配(单个分配> 86KB),其中有很多和可能会引起关注。
答案 2 :(得分:0)
我无法确定它是否明智,但如果您不希望收集它,请使用以下代码:
GC.KeepAlive(object);
答案 3 :(得分:0)
您需要注意,项目不会以大对象堆(> 85K)结束。如果它们仍然是驻留的,那不是问题,但如果数据被换入和换出,你可能会因为LOH没有被压缩而最终导致内存碎片化。