C#,为什么GC每秒运行几次?

时间:2016-04-11 18:48:03

标签: c# .net garbage-collection

我正在开发一个创建交互式图表的程序。但是,即使程序的渲染层被禁用,也会出现以下问题。

在我的应用程序的某些屏幕上,根据Visual Studio 2015诊断工具,GC每秒大约运行4次,从而导致我的应用程序性能下降(从120fps降至15fps)。

我花了一些内存快照,期望看到意外的分配,但根据快照,每隔几秒就只有一两个System.Internal.HandleCollector + HandleType的分配和集合,这似乎是正常的,即使问题是发生了。

我注意到的其他一些事情:

  • 这种情况发生在多台机器上。
  • 无论是否附带调试器,都会发生这种情况。
  • 应用程序的大部分CPU时间都在clr.dll中。
  • 每次GC运行的原因都列为“小对象堆” 即使在快照中没有可观察的分配时,“分配”。

此时我很难过。有没有人看到过这种情况或知道我应该在哪里开始调试?

3 个答案:

答案 0 :(得分:4)

来自https://msdn.microsoft.com/en-us/library/ee787088(v=vs.110).aspx

  

当满足下列条件之一时,就会发生垃圾收集:

     

系统物理内存较低。

     

托管堆上已分配对象使用的内存超过了可接受的阈值。在该过程运行时,该阈值会不断调整。

     

调用GC.Collect方法。几乎在所有情况下,您都不必调用此方法,因为垃圾收集器会持续运行。此方法主要用于独特的情况和测试。

也许您正在满足上面列出的三个条件之一。您的应用程序似乎正在使用大量内存,因此正在运行垃圾收集以尝试清理某些对象以尝试释放一些内存。

也可能GC.Collect()在您的代码中某处,并导致垃圾收集器再次运行。

Here是与垃圾收集相关的一些故障排除指南。特别是一节似乎涉及到您所遇到的问题。在标记为&#34的部分下;问题:垃圾收集过程中的CPU使用率太高"它说:

  

垃圾回收期间CPU使用率很高。如果在垃圾收集中花费了大量的处理时间,则收集的数量太频繁或者收集持续时间太长。托管堆上对象的分配率增加会导致垃圾收集更频繁地发生。降低分配率可以减少垃圾收集的频率。

     

您可以使用Allocated Bytes / second性能计数器监控分配率。有关更多信息,请参阅.NET Framework中的性能计数器。

     

收集的持续时间主要是分配后存活的对象数量的一个因素。如果仍有许多对象需要收集,垃圾收集器必须经过大量内存。压缩幸存者的工作非常耗时。要确定在集合期间处理了多少对象,请在指定代的垃圾回收结尾处的调试器中设置断点。

答案 1 :(得分:2)

尝试使用此更改app.config并进行运行

<configuration>
   <runtime>
      <gcServer enabled="true"/>
   </runtime>
</configuration>

有关GC的更多有趣详情,请访问https://msdn.microsoft.com/en-us/library/ee787088(v=vs.110).aspx

答案 2 :(得分:0)

您应该检查调用GC的代码。通常它的运行速度远远低于每秒4次。将调试器或分析器附加到有问题的实例,以查找调用GC的位置。也许是在第三方图书馆。或者你想不到的一些代码。