.NET 垃圾收集延迟
我正在使用内存分析器、dotTrace 和 perfmon 计数器分析 C# 应用程序中的内存。我无法回答的一个问题是:垃圾收集在我的应用程序中导致的最大延迟是多少?我可以通过使用垃圾收集中的时间百分比来获得近似值,但是有什么方法可以计算各个收集的时间吗?
I'm profiling memory in a C# application using a memory profiler, dotTrace, and perfmon counters. The one question that I have not been able to answer is: What is the maximum latency that garbage collection causes in my application? I can get an approximate value for this by using the % time in Garbage collection, but is there any way to time individual collections?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看起来你在问 2 个问题
1- GC 是否有最大延迟?
2-如何安排单独GC收集的时间?
对于 #1,GC 吞吐量大约为 200MB/秒/堆。这意味着 GC 能够在 1 秒内收集大小为 100MB 的堆。 perheap 概念是因为服务器 GC,因为我们为每个 CPU 创建 1 个堆。
因此,如果你有一个巨大的堆,你会看到很大的延迟。
请记住,当 GC 收集内存时,它会以短暂的方式执行此操作,因此与完整 GC 收集相比,Gen0/Gen1 收集非常便宜。
在.NET 4.0中,我们添加了一个功能来最小化客户端应用程序的GC延迟,该功能在GC并发模式下默认启用。在此模式下,我们尝试在应用程序运行时在后台线程中收集堆。这会为客户端应用程序带来更好的暂停时间
For#2:我们在 .net 框架中有一个非常强大的跟踪功能,称为 ETW(它在 Windows 中可用,我们在 CLR 中利用它)。 ETW 代表 Windows 事件跟踪 ()。我们当GC即将开始时触发ETW事件,并且当GC完成时使用这些ETW事件,您可以
参考CLR ETW 参考。此外,对于允许您处理 ETW 事件的良好托管库,查看 TraceEvent
希望有所帮助。
谢谢
It looks like you are asking 2 questions
1- Is there a max latency for the GC?
2- How to time individual GC collection?
For #1, the GC throughput is roughly 200MB/sec/heap. This means the GC is able to collect a heap of size 100MB in 1 second. The perheap notion is because server GC, since we are creating 1 heap per CPU.
So, if you have a huge heap, you can see big latencies.
Keep in mind that when GC collect the memory, it does this in an ephemeral way, so Gen0/Gen1 collections are very cheap compared to full GC collections.
In .NET 4.0 we added a feature to minimize the GC latency for client applications, this feature is enabled by default under the GC Concurrent mode. In this mode, we try to collect the heap in a background thread while the application is running. This results in better pause time for client applications
For#2: We have a very powerful tracing in the .net framework called ETW (it is available in Windows, and we take advantage of it in the CLR ). ETW stands for Event Tracing For Windows (. We fire ETW events when a GC is about to start, and when a GC finish. using these ETW events, you can calculate the time spent in each GC.
For more information you can refer to the CLR ETW reference. Also, for a nice managed library that allows you to deal with ETW events, check out TraceEvent
Hope this help.
Thanks
可以使用 GC.RegisterForFullGCNotification() 方法对第 2 代收集(慢速收集)进行计时。然而,这需要收集器的服务器版本(.config 文件中的
元素)。经典的海森堡式,它打败了这一点,因为只有工作站版本支持并发第 2 代集合,它们可以显着改善延迟。它产生的实际延迟非常不可预测,它很大程度上取决于程序中线程在并发收集正在进行时分配和填充 gen #0 和 #1 的速率。强烈建议不要问这个问题。
It is possible to time gen #2 collections (the slow ones) with the GC.RegisterForFullGCNotification() method. That however requires the server version of the collector (
<gcserver>
element in the .config file).Classic Heisenbergian, it defeats the point since only the workstation version supports concurrent gen #2 collections, they can significantly improve latency. The actual latency it produces is very unpredictable, it highly depends on at what rate threads in your program are allocating and filling gen #0 and #1 while a concurrent collection is in progress. Not having to ask this question is strongly recommended.
我认为没有“最大延迟”。 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。
I don't think there is a 'maximum latency.' GC fires up when it has to - when there is memory pressure. The same app running on a machine with 2GB will see more frequent collections than the same app on a 4GB machine.
one thing I had a real hard time with when starting with .NET was watching memory grow. Man, that was scary because I thought I had leaks. But over time, you see the GC settle down and everything runs along swimmingly.
If you get OOM exceptions or other bad behavior, that's when you worry. otherwise, let GC do its thing.
EDIT: zneak makes a great comment - I may have misunderstood your question.
Time spent in GC also depends on a lot of factors, Which generation is being collected? Gen0's are very quick. Gen1's take longer and Gen2's longer still. With good memory utilization I look for 10 Gen1 collections for every Gen2, and 10 Gen0's for every Gen1. Over the course of a day on our heavily-used web site I may see 10,000 Gen0's, 1000 Gen1's, and 100 Gen2's. YMMV.