我正在读一本 博客条目 作者:Josh Smith,他使用缓存机制来“减少托管堆碎片”。他的缓存减少了创建的短期对象的数量,但代价是执行速度稍慢。

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

有帮助吗?

解决方案

  

不要太快。它通常是很便宜的有短暂的对象。对于高速缓存是有利可图的话会有是(很)多candiadates,他们应该活得足够长,以使它的下一代。

  

你怎么能诊断,如果这是一个问题?

通过一个探查。我不太确定文章的作者这样做。

  

如何的问题多少是托管堆碎片如C#托管语言?

据我知道这是罕见的。 .NET具有压缩垃圾收集器,分段的,其防止大多数形式。存在与大对象堆有时。

的问题

编辑:

当你通过文章下面的评论,你会发现有人测量了一下,发现缓存比创造新的EventArgs每次慢了许多。

<强>结论:测量在开始优化之前。这不是个好主意/例子。

其他提示

除非您每秒处理超过 10K 个小型短期对象,否则在具有合理 RAM 量的现代计算机上这根本不应该成为问题。

因此,首先您应该在所有合理的情况下运行代码,如果它足够快 - 不要担心。

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

redgate ANTS Profiler 还监控这些统计数据。

托管堆碎片通常是由于对象固定造成的。当托管代码将对象指针传递给本机代码时,对象将被固定,并且该对象无法移动,因为引用已传递给本机代码。当有大量 I/O 活动时,这种情况很常见。就像上面提到的,它通常只发生在 LOH 中。

这是一个例子 Gen0 堆中的碎片

与这里给出的其他答案不同,我声明:是的,我们应该处理碎片问题!它不仅适用于托管堆,还适用于所有处理(至少)的应用程序

  • 许多“大”资源
  • 大量分配模式。

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

如何检测呢?当 LOB 堆上存在较大压力时。如何查出它是?同时使用.NET性能计数器“Collection Count Gen 0...2”。如果从 LOB 分配了太多大对象,则所有计数器都会以相同的方式演变。意思是,基本上所有的集合都是 昂贵的 第 2 代收藏。在这种情况下,就应该采取一些措施。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top