我正在阅读Josh Smith的blog entry,他在那里使用缓存机制来“减少托管堆碎片”。他的缓存减少了创建的短期对象的数量,但代价是执行速度稍慢。
在C#等托管语言中管理堆碎片有多少问题?你如何诊断它是否是一个问题?在什么情况下你通常需要解决它?
答案 0 :(得分:7)
当
不太快。拥有短寿命物体通常非常便宜。为了使缓存有利可图,必须有(非常)许多候选人,他们应该活得足够长,以便下一代。
如何判断这是否是一个问题?
使用Profiler。我不太确定文章的作者那样做过。
在C#等托管语言中管理堆碎片有多少问题?
据我所知,这种情况很少见。 .NET有一个压缩的垃圾收集器,可以防止大多数形式的碎片。有时会出现大对象堆的问题。
编辑:
当你浏览文章下面的评论时,你会发现有人测量了它,发现缓存比每次创建新的eventar慢很多。
结论:在开始优化之前进行衡量。这不是一个好主意/例子。
答案 1 :(得分:4)
除非您每秒处理10K +小型短寿命对象,否则在具有合理RAM量的现代计算机上应该不会出现问题。
首先,您应该在所有合理的情况下运行代码,如果速度足够快,请不要担心。
如果你对速度不满意,你会看到代码有时“窒息”或只是好奇,你可以在性能监视器应用程序中监视各种.NET内存统计信息(http://msdn.microsoft.com/en-us/library/x2tyfybc.aspx)(作为Windows的一部分) )。具体而言,您对GC中的%Time感兴趣。
redgate ANTS探查器也会监控这些统计数据。
答案 2 :(得分:1)
托管堆碎片通常是因为对象的固定。当托管代码将对象指针传递给本机代码时,对象会被固定,并且由于引用被传递给本机代码,因此无法移动对象。当有大量I / O活动时,这是很常见的。如上所述,它通常只发生在LOH。
的示例答案 3 :(得分:-1)
与此处给出的其他答案不同,我指出:是的,应该注意碎片!它不仅适用于托管堆,也适用于所有处理(至少)的应用程序
由于LOB没有得到压缩,因此 - 随着时间的推移 - 一旦对象的大小和数量超过某个值(这与可用的总体最大堆值相关),很可能会出现碎片。如果是这样,唯一安全的方法是限制对这些对象的即时拥有引用的数量。缓存(池)只有在池中的对象可以重用时才有用。有时,如果这些资源由不同长度的数组组成,则它们可能不容易重复使用。所以汇集在这里可能没有多大帮助。
如何检测?什么时候LOB堆上有很大的压力。怎么弄清楚呢?同时使用.NET性能计数器“Collection Count Gen 0 ... 2”。如果从LOB分配了太多大对象,则所有计数器都将以相同的方式发展。意思是,基本上所有集合都是昂贵的第2代集合。在这种情况下,应该做点什么。
关于较小的物体,我会让GC在Gen 0系列中完成所有工作而不用担心。