我正在使用内存分析器,dotTrace和perfmon计数器在C#应用程序中分析内存。我无法回答的一个问题是:垃圾收集在我的应用程序中导致的最大延迟是多少?通过使用垃圾收集中的%time,我可以得到一个近似值,但有没有办法计算个别收集的时间?
答案 0 :(得分:8)
看起来你问的是2个问题 1- GC是否有最大延迟? 2-如何为个别GC收集时间?
对于#1,GC吞吐量大约为200MB / sec /堆。这意味着GC能够在1秒内收集大小为100MB的堆。 perheap概念是因为服务器GC,因为我们每个CPU创建1个堆。
所以,如果你有一个巨大的堆,你可以看到很大的延迟。 请记住,当GC收集内存时,它会以短暂的方式执行此操作,因此与完整的GC集合相比,Gen0 / Gen1集合非常便宜。
在.NET 4.0中,我们添加了一项功能,可以最大限度地减少客户端应用程序的GC延迟,默认情况下,此功能在GC并发模式下启用。在此模式下,我们尝试在应用程序运行时在后台线程中收集堆。这样可以为客户端应用程序提供更好的暂停时间
对于#2:我们在.net框架中有一个非常强大的跟踪,称为ETW(它在Windows中可用,我们在CLR中利用它)。 ETW代表Event Tracing For Windows (。当GC即将启动时,以及GC完成时,我们会触发ETW事件。使用这些ETW事件,您可以计算每个GC所花费的时间。
有关详细信息,请参阅CLR ETW reference。此外,对于一个允许您处理ETW事件的良好托管库,请查看TraceEvent
希望这有帮助。 感谢
答案 1 :(得分:4)
可以使用GC.RegisterForFullGCNotification()方法对gen#2集合(慢速集合)进行计时。但是,这需要收集器的服务器版本(.config文件中的<gcserver>
元素)。
Classic Heisenbergian,它击败了这一点,因为只有工作站版本支持并发第2代集合,它们可以显着改善延迟。它产生的实际延迟非常不可预测,它在很大程度上取决于程序中的线程在并发集合正在进行时分配和填充gen#0和#1的速率。强烈建议不要问这个问题。
答案 2 :(得分:2)
我认为没有“最大延迟”。必要时GC会启动 - 当有内存压力时。在2GB机器上运行的相同应用程序将比4GB机器上的同一应用程序看到更频繁的收集。
我开始使用.NET时遇到的一件事就是看内存增长。男人,这太吓人了,因为我以为我有泄漏。但随着时间的推移,你会看到GC稳定下来,一切都在游泳。如果您遇到OOM异常或其他不良行为,那就是您担心的时候。否则,让GC做它的事情。
编辑:zneak做出了很好的评论 - 我可能误解了你的问题。
在GC中花费的时间还取决于很多因素,正在收集哪一代? Gen0很快。 Gen1需要更长时间,Gen2需要更长时间。凭借良好的内存利用率,我为每个Gen2寻找10个Gen1集合,为每个Gen1寻找10个Gen0集合。在我们频繁使用的网站上的一天中,我可能会看到10,000 Gen0,1000 Gen1和100 Gen2。 YMMV。