Reputation: 171
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?
Upvotes: 12
Views: 2183
Reputation: 4108
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
Upvotes: 9
Reputation: 942518
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.
Upvotes: 4
Reputation: 19765
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.
Upvotes: 2