长时间将大量对象保留在内存中

时间:2009-02-19 12:50:12

标签: .net asp.net performance garbage-collection

在我的ASP.NET应用程序中,我有一个包含大量对象的字典(比如说大到1M,之后可能会变大),存储在字典中的对象是引用类型而不是struct类型,字典意味着作为这种类型对象的缓存(我有理由不使用ASP.NET缓存来缓存这种类型的对象,我用它来缓存其他东西)。

这会导致GC出现问题吗?我一直听说长寿命物体会影响GC的性能并导致它在收集过程中花费更多时间,是否有避免这种情况?据我所知,字典(和对象)最终应该在Gen2中,除非系统内存不足,否则GC不会收集它(如果我错了请纠正我),那么如果系统有很多内容呢?记忆,GC仍会以相同的频率收集Gen2吗?必须有其他应用程序长时间缓存大量数据,我想知道它们如何避免GC的问题。

任何建议都非常感谢......

4 个答案:

答案 0 :(得分:3)

在大约1M条目中,基础数组的字典将不可避免地最终出现在LOH中。鉴于此,最好将其预分配的大小与其最终包含的条目数相当(这可能会严重反击,并且可能是测试模式中的一种痛苦)。

字典中的对象应该提供非常好的哈希码实现。这与内存使用无直接关系,只与查找效率有关。但是,如果您为较少的内存使用交换较高的加载因子,则错误的哈希最终可能会使字典行为降级到不再是O(1)的程度。

它包含的长寿命项目应该是:

  1. (最佳情况)不包含作为引用类型的实例字段。

    • 然后GC不需要遍历数组中的每个对象(GC实现可能不会执行此优化,因此您的milage可能会有所不同)。
  2. 确保您的应用程序不会进入Mid Life Crisis样式行为

    • 触发您希望避免的更多gen2集合。
  3. 它们包含的任何引用都不应指向Gen0或Gen1堆

    • 这会导致大量写入障碍,这会降低你的gen 0 / gen 1集合的速度。
  4. 由于您声明这是一个缓存但未提及您的保留政策,我认为此advice也值得一提。

    你正在缓存的对象类型的一些指示可能是相关的4 / 8MB或连续内存是非常多的,即使使用现代处理器缓存,因此对缓存的频繁请求可能比具有更紧密,更小的缓存更糟糕的性能更好的保留政策。

答案 1 :(得分:1)

你理解这个场景是正确的,只要系统不渴望内存Gen2集合应该是不常见的,因此在那里保留许多长寿命对象应该不是问题。

如果您必须仔细编码以避免GC出现“问题”,GC将无法很好地完成其工作。

真正需要关注的唯一区域是大量分配(单个分配> 86KB),其中有很多可能会引起关注。

答案 2 :(得分:0)

我无法确定它是否明智,但如果您不希望收集它,请使用以下代码:

GC.KeepAlive(object);

答案 3 :(得分:0)

您需要注意,项目不会以大对象堆(> 85K)结束。如果它们仍然是驻留的,那不是问题,但如果数据被换入和换出,你可能会因为LOH没有被压缩而最终导致内存碎片化。