سؤال

I'm investigating GC and memory use in our application, and have noticed we seem to have thousands of finalization survivors. Unfortunately, the number alone doesn't really tell me whether we have a problem. We are seeing general performance issues however, and we do have high memory use and spend a lot of time in GC.

Ideally, nothing we have any control over should enter the finalization queue. It's a bug if it does. Is there some method or tool I can use to check this? One suggestion I've heard is to have a special build with finalizers that log whenever they are executed, but this is quite a lot of effort, and will only work with the objects whose types we own. Is there an easier way?

And is it worth investigating finalization survivors? If so, how?

هل كانت مفيدة؟

المحلول

Use WinDbg with Psscor2 or Psscor4 extension (depending version used by you application). Unfortunately there is no version for .NET 4.5 yet. After setting up the debugging environment (installing WinDbg and copying to its folder Psscor files), create a dump of the process. You can do it easily for example with help of Procdump tool:

procdump -ma <PID>

Then load dump using File -> Open Crush Dump option. Load appropriate version of Psscor:

.load psscor4

Then execute command to download symbols from Microsoft servers (if needed), make sure that you have an internet connection:

!symfix

And from now you should have access to plenty very interestings command (look for !help to list them). To see finalization queue:

!finalizequeue

There you will have a list of object, like:

7aa143e0      166       20,584 System.Diagnostics.PerformanceCounter
79b5f6c8      543       21,720 System.Reflection.Emit.DynamicResolver
673893a8      953       22,872 System.Web.HttpResponseUnmanagedBufferElement

This might help you a lot. But you can also inspect those objects (!do 7aa143e0), find references (!gcroot <address>) etc.

نصائح أخرى

And is it worth investigating finalization survivors?

Yes, because finalization has a performance and resource impact.

If so, how?

I suggest code inspection.

Does your types have finalizers? If yes are these properly implemented? You only need a finalizer if you directly control an unmanaged resource. And if you have a finalizer you should implement IDisposable and use deterministic cleanup. Doing that will ensure that your finalizers are never called. The call to GC.SuppressFinalize(this) in the Dispose method ensures that an instance is not finalized because it has already been disposed.

If the finalizers are in library code then these types will (or should) implement IDisposable and you will have to deterministically dispose these instances to make sure that their finalizers are never called.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top