【问题标题】:When to address managed heap fragmentation何时解决托管堆碎片
【发布时间】:2010-04-08 14:48:17
【问题描述】:

我正在阅读 Josh Smith 的 blog entry,他使用缓存机制来“减少托管堆碎片”。他的缓存减少了正在创建的短期对象的数量,但代价是执行速度稍慢。

在像 C# 这样的托管语言中,托管堆碎片有多少问题?如果是问题,您如何诊断?在什么情况下您通常需要解决它?

【问题讨论】:

    标签: .net caching heap-fragmentation


    【解决方案1】:

    什么时候

    不要太快。拥有短寿命的对象通常非常便宜。为了使缓存能够盈利,必须有(非常)许多候选者,并且他们应该活得足够长以使其能够传给下一代。

    如果是问题,您如何诊断?

    使用探查器。我不太确定这篇文章的作者是否这样做了。

    在像 C# 这样的托管语言中,托管堆碎片有多少问题?

    据我所知,这种情况很少见。 .NET 有一个压缩垃圾收集器,可以防止大多数形式的碎片。大型对象堆有时会出现问题。


    编辑:

    当你浏览文章下面的 cmets 时,你会发现有人测量了它,发现缓存比每次创建新的 eventargs 慢很多。

    结论:在开始优化之前进行测量。这不是一个好主意/例子。

    【讨论】:

    • +1。无法忍受人们在没有正当理由的情况下花时间“优化”。
    • 是的——缓存是以牺牲执行速度为代价的。
    • ...但如果它阻止 GC 一直收集 LOH,它肯定可以支付
    • @user492238 - 不,EventArgs 对于 LOH 来说太小了。
    • 不确定你的意思。我没有声称 eventargs 在 LOH 上?我想说缓存可以在没有针对 GC 进行优化的情况下获得回报。这通常与 LOH 有关。取 1 个 Mill LOH 对象(普通数组)并在循环中进行一些计算。我不需要探查器提前知道,与依靠 GC 从 LOH 中回收它们相比,重用它们在性能方面要好得多。 (是的,一般来说我们应该使用分析器;)
    【解决方案2】:

    除非您每秒处理 10K+ 小短寿命对象,否则在具有合理 RAM 量的现代计算机上这根本不是问题。

    所以首先你应该在所有合理的场景中运行代码,如果它足够快 - 不用担心。

    如果您对速度不满意,有时会看到代码“阻塞”或只是好奇,您可以在性能监视器应用程序(作为 Windows 的一部分)中监控各种 .NET 内存统计信息 (http://msdn.microsoft.com/en-us/library/x2tyfybc.aspx)。具体来说,您对 GC 中的 % Time 感兴趣。

    redgate ANTS profiler 也会监控这些统计数据。

    【讨论】:

    【解决方案3】:

    托管堆碎片通常是由于对象的固定。当托管代码将对象指针传递给本机代码并且由于引用传递给本机代码而无法移动对象时,对象将被固定。当有很多 I/O 活动时,这很常见。如上所述,它通常只发生在 LOH 中。

    这是Fragmentation in Gen0 Heap的示例

    【讨论】:

    • 由于 LOH 上的对象根本没有移动,因此如果它们也被固定,则没有任何区别。
    【解决方案4】:

    与此处给出的其他答案不同,我声明:是的,应该注意碎片化!它不仅适用于托管堆,而且适用于所有应用程序处理(至少)

    • 中有许多“大型”资源
    • 一种繁重的分配模式。

    由于 LOB 没有被压缩,随着时间的推移,一旦对象的大小和数量超过某个值(这与可用的总最大堆大小有关),它很可能会变得碎片化。如果是这样,唯一安全的方法是限制对这些对象的即时持有引用的数量。如果可以重用池化的对象,缓存(池)只会有所帮助。有时,如果这些资源由不同长度的数组组成,它们可能不容易重用。因此,池化在这里可能没有多大帮助。

    如何检测?当 LOB 堆上的压力很大时。如何找出它是?同时使用 .NET 性能计数器“Collection Count Gen 0...2”。如果从 LOB 中分配了太多的大对象,所有的计数器都会以相同的方式演化。意思是,基本上所有的收藏都是昂贵的第二代收藏。在这种情况下,应该做点什么。

    对于较小的对象,我会让 GC 完成 Gen 0 集合中的所有工作,不用担心。

    【讨论】:

    • 感谢您的反对。请留下一些推理的评论,以便改进答案,并让其他人从您的经验中受益!
    猜你喜欢
    • 2012-04-03
    • 1970-01-01
    • 2010-09-08
    • 2014-07-14
    • 2011-07-12
    • 2010-12-08
    • 2010-12-13
    • 2010-09-14
    相关资源
    最近更新 更多