Prevent .NET Garbage collection for short period of time
Asked Answered
P

2

86

I have a high performance application that is handling a very large amount of data. It is receiving, analysing and discarding enormous amounts of information over very short periods of time. This causes a fair amount of object churn that I am currently trying to optimize, but it also causes a secondary problem. When Garbage Collection kicks in it can cause some long delays as it cleans things up (by long I mean 10s to 100s of milliseconds). 99% of the time this is acceptable, but for brief windows of time about 1-2 minutes long I need to be absolutely sure that Garbage Collection does not cause a delay. I know when these periods of time will occur beforehand and I just need a way to make sure that Garbage collection doesn't happen during this period. The application is written in C# using .NET 4.0 Framework and uses both managed and unmanaged code if that matters.

My questions are;

  1. Is it possible to briefly pause Garbage Collection for the entire program?
  2. Is it possible to use System.GC.Collect() to force garbage collection before the window I need free of Garbage Collection and if I do how long will I be Garbage Collection free?
  3. What advice do people have on minimizing the need for Garbage Collection overall?

Note - this system is fairly complex with lots of different components. I am hoping to avoid going to a approach where I have to implement a custom IDisposable interface on every class of the program.

Pandiculation answered 15/5, 2011 at 1:17 Comment(6)
this has some overlap with #3074934Margherita
How would a custom IDisposable implementation on every class help solve your problem? Those objects would still need to be GC'ed after disposal, wouldn't they?Comanchean
IDisposable has nothing to do with Garbage Collection.Spermato
@Comanchean - With a lot of work with an IDisposable interface I could have each object check to see if the app is in a critical period and prevent finalization until after that period is done. This aproach would take A LOT of effort and has MANY possible downsides, but it could theoreticly be used. Once the critical period is finished there would be a ton of cleanup from the enourmous mass of suddenly finalized objects. Not particularly pretty.Pandiculation
@Doug: I still don't see how IDisposable helps that scenario at all, since disposal and GC are pretty-much orthogonal. Finalisation and GC are related, but adding finalisers to your classes will end up making the GC do more work, not less.Comanchean
@Comanchean Using the IDisposable interface you catch the object before it is finalized. At that point you check a singleton reference in the program to determine if the app is in a critical path state. If so you short circuit the finalization and add the object to a cleanup queue for later disposal. As long as the object is referenced in that cleanup queue it is not subject to GC. When the critical path state is done then all objects in the cleanup queue are destroyed and finalized. I honestly don't like this at all and I am not sure there wouldn't be huge side effects. It was just a thought.Pandiculation
A
113

.NET 4.6 added two new methods: GC.TryStartNoGCRegion and GC.EndNoGCRegion just for this.

Apps answered 14/8, 2015 at 10:7 Comment(2)
Thanks for the new info. It would be great if I had this back when this problem was relevant. Hopefully, it will help new people with the same problem.Pandiculation
@Pandiculation out of curiosity, what did you end up doing back then?Manella
S
81
GCLatencyMode oldMode = GCSettings.LatencyMode;

// Make sure we can always go to the catch block, 
// so we can set the latency mode back to `oldMode`
RuntimeHelpers.PrepareConstrainedRegions();

try
{
    GCSettings.LatencyMode = GCLatencyMode.LowLatency;

    // Generation 2 garbage collection is now
    // deferred, except in extremely low-memory situations
}
finally
{
    // ALWAYS set the latency mode back
    GCSettings.LatencyMode = oldMode;
}

That will allow you to disable the GC as much as you can. It won't do any large collections of objects until:

  • You call GC.Collect()
  • You set GCSettings.LatencyMode to something other than LowLatency
  • The OS sends a low-memory signal to the CLR

Please be careful when doing this, because memory usage can climb extremely fast while you're in that try block. If the GC is collecting, it's doing it for a reason, and you should only seriously consider this if you have a large amount of memory on your system.

In reference to question three, perhaps you can try reusing objects like byte arrays if you're receiving information through filesystem I/O or a network? If you're parsing that information into custom classes, try reusing those too, but I can't give too much good advice without knowing more about what exactly you're doing.

Here are some MSDN articles that can help too:

Note: GCSettings.LatencyMode = GCLatencyMode.LowLatency can only be set if GCSettings.IsServerGC == false. IsServerGC can be changed in App.config:

  <runtime>
    <gcServer enabled="false" />
  </runtime>
Stegman answered 15/5, 2011 at 1:38 Comment(2)
A few questions if you don't mind. 1. I know the general period of time when a critical event will happen, but it will be triggered from a data element being recieved from a multicast broadcast. I want to prevent the GC from delaying the reciept of that data. What do you recomend? 2. Is there a performance hit as you enter either the ConstrainedRegion or switch to LowLatency mode? Could this be done as soon as I see a specific data item without taking an entry performance hit? BTW, very useful stuff - Thanks.Pandiculation
For 1, I'd say if the general period of time is small, on the order of a few seconds, then you could probably set the GC to LowLatency until the message arrives. Any longer than that, and I'd say there isn't much you can do to my knowledge. If you absolutely must have no GC delay, you could try to receive the broadcast in another process and then marshal it over to your main process, but that complicates things significantly. For 2, entering a CER I believe comes with a performance hit as you enter and exit it, but I've never measured it, nor setting the latency mode myself.Stegman

© 2022 - 2024 — McMap. All rights reserved.