GC on external process
Asked Answered
M

3

7

Is it possible to force GC on an external process? I mean without attaching to Visual Studio/windbg etc. I know it might be possible to do it with something like VS Immediate window.

EDITenter image description here It looks like this could be done via PerfView but I could find much info as if this does a full GC or what. Any ideas?

Mason answered 3/3, 2015 at 21:12 Comment(2)
Why do you even want to?Alessandro
I did not do the downvoting but if you look at the text for the button it says "This question does not show any research effort; it is unclear or not useful". Your did not show any research effort at the time of the downvote, that is likely why it was downvoted.Circumsolar
C
2

No, neither Windows nor .NET exposes any kind of API you could use to force a GC on a external process without attaching a debugger to it.

You must attach a debugger and use that route to force a GC.

Circumsolar answered 3/3, 2015 at 21:24 Comment(3)
@PaulSnow The PerfView either temporarily attaches a debugger, forces a GC, then detaches or has a debugger attached the entire time. Which you said you did not want to do in your solution.Circumsolar
You are right, I probably wasn't clear in my question. I found some people suggesting to install VS and do a GC.Collect from its immediate windows. That sound like a very heavy solution ( requiring to install VS). So I basically didn't want to use that one.Mason
If you want to write a program to do it then you need to write code to interface with the DebuggingAPI which is not a easy task to do (It is all unmanaged COM calls, I would not do it as your first COM interop project). You might be able to get away a command line program that wrapps the interface like MDbg. Just call that from your program and pass the commands along.Circumsolar
C
15

Your options for forcing a GC from an external process are

1) Attach with the debugger API and call a GC.Collect() method using that API. I tried to do this with PerfView originally but it does not work if the process is blocked in native code (the debugger does not attach until it runs managed code again), which was unacceptable.

2) Inject a profiler (which since V4.5 you can do with attach) and call an API on that to do a GC. This does work (assuming another profiler is not already attached). This is in fact what PerfView does.

3) Use Event Tracing for Windows (ETW). Since V4.5 of the runtime, there is a keyword called GCHeapCollect, that if set will cause the runtime to do a full GC. You need to be Admin to enable ETW providers, so this only works if you 'controlling' process can be admin. If you wish to do this, using the TraceEvent Nuget package (see http://blogs.msdn.com/b/vancem/archive/2014/03/15/walk-through-getting-started-with-etw-traceevent-nuget-samples-package.aspx) Normally ETW sends request to all processes on the system, but you can make it process specific (on Win 8 or later) using the TraceEventProviderOptions.

Note that none of this is meant for casual use. You should be something like a debugger or a profiler to be doing such things. Forcing GCs in other processes without their participation is generally evil....

Vance Morrison .NET Performance Architect.

Contain answered 3/3, 2015 at 23:47 Comment(1)
Thanks Vance. I've implemented your ETW suggestion below, without knowing much at all about ETW or the library. it would be great if you could check it for any obvious issues or improvements.Inattention
I
3

If anyone is looking for code to do this via ETW (as suggested by @Vance Morrison above), the below is what I've come up with, using the Microsoft.Diagnostics.Tracing.TraceEvent nuget package and adapting the samples provided.

NB there might be a better/easier way to do it, but it works consistently without issues for my use case.

Replace <PROCESS_ID> with your process ID integer.

using (var userSession = new TraceEventSession("TriggerGC"))
{
    userSession.EnableProvider(
        ClrTraceEventParser.ProviderGuid, 
        TraceEventLevel.Verbose, 
        (ulong)(ClrTraceEventParser.Keywords.GCHeapCollect), new TraceEventProviderOptions
        {
            ProcessIDFilter = new List<int>() { <PROCESS_ID> }
        });

    userSession.Source.StopProcessing();    
}
Inattention answered 11/6, 2020 at 14:21 Comment(1)
+1: Thanks for the valuable information. I have created a version that also reports some progress and status about the collection here.Chemaram
C
2

No, neither Windows nor .NET exposes any kind of API you could use to force a GC on a external process without attaching a debugger to it.

You must attach a debugger and use that route to force a GC.

Circumsolar answered 3/3, 2015 at 21:24 Comment(3)
@PaulSnow The PerfView either temporarily attaches a debugger, forces a GC, then detaches or has a debugger attached the entire time. Which you said you did not want to do in your solution.Circumsolar
You are right, I probably wasn't clear in my question. I found some people suggesting to install VS and do a GC.Collect from its immediate windows. That sound like a very heavy solution ( requiring to install VS). So I basically didn't want to use that one.Mason
If you want to write a program to do it then you need to write code to interface with the DebuggingAPI which is not a easy task to do (It is all unmanaged COM calls, I would not do it as your first COM interop project). You might be able to get away a command line program that wrapps the interface like MDbg. Just call that from your program and pass the commands along.Circumsolar

© 2022 - 2024 — McMap. All rights reserved.