How to determine if and when the Garbage Collector is being run?


I have made steps to try to eliminate the Garbage Collector. How can I tell if I succeeded?
I set the GCEnableMessages to true but it never prints anything even when I run a program with a lot of allocating.


1 Like

then you are not doing it right… Debug.EnableGCMessages(true) should be all you need.

You can report the memory available with Debug.GC(false), and you can force GC as well with Debug.GC(true) - together these two can show you if things are churning or if they’re stable.

Usually, GC will occur if you do nothing. I have never had to enable GC.

@ John@ GHI - can you test on G30/G80 to see if the firmware will output GC messages? When I run the following code on a G80 (Panda3) I get no debug messages. When I run it on G400 (Raptor) I get them.

while (true)

[quote]GC: 1msec 229752 bytes used, 66876012 bytes available
Type 0F (STRING ): 336 bytes
Type 11 (CLASS ): 5076 bytes
Type 12 (VALUETYPE ): 96 bytes
Type 13 (SZARRAY ): 1992 bytes
Type 03 (U1 ): 156 bytes
Type 04 (CHAR ): 492 bytes
Type 07 (I4 ): 36 bytes
Type 11 (CLASS ): 1308 bytes
Type 15 (FREEBLOCK ): 66876012 bytes
Type 17 (ASSEMBLY ): 25044 bytes
Type 18 (WEAKCLASS ): 48 bytes
Type 19 (REFLECTION ): 192 bytes
Type 1B (DELEGATE_HEAD ): 180 bytes
Type 1D (OBJECT_TO_EVENT ): 48 bytes
Type 1E (BINARY_BLOB_HEAD ): 193020 bytes
Type 1F (THREAD ): 384 bytes
Type 20 (SUBTHREAD ): 48 bytes
Type 21 (STACK_FRAME ): 456 bytes
Type 27 (FINALIZER_HEAD ): 48 bytes
Type 31 (IO_PORT ): 72 bytes
Type 34 (APPDOMAIN_HEAD ): 72 bytes
Type 36 (APPDOMAIN_ASSEMBLY ): 2640 bytes
GC: performing heap compaction…[/quote]

1 Like

@ Brett - This has been the case for as long as I have been using GHI/Netmf, in that I have never seen any GC debug messages output from Cerb or G80 based boards but now that I have switched to G120 it always works (and can be disabled correctly). I just wish I knew what to do with the information… :think: :-[

@ Brett - We were able to reproduce the issue, thanks.

@ jwizard93 - I’m interested in the exact same question. I worked pretty hard and bothered everyone on this forum in my efforts to prevent the GC from running. I still don’t know how to interpret the results from Debug.GC(false) to know if the GC has run. If you figure it out, please let me know. You may be interested in these threads and if you have more techniques that prevent the GC from running, please let us know.

1 Like

Just getting back to this thread; I have been in manufacturing mode for some time getting ready for GDC. Thank you everyone for your responses.

Very happy with the latency seen with six of our units communicating with a single receiver connected to a Unity app. The NETMF continues to be a promising path all the way through to product stages.

@ Gene - Appreciate the links. I have been analyzing the Qaudro for quite some time trying to determine if this example means I will be able to do what I need to do. I will be adopting the practices seen in that program. The other link about garbage disposal as enlightened me to the fact that I simply have no idea what GC really does. I thought it was something that might be going on all the time making my control loop longer and indeterminate at every iteration. It seems in most people’s experience it runs once every few minutes and may run for a very long time. I haven’t seen this yet, but I’m afraid to ship a product without knowing how it might affect.

Which brings me to … @ John - am I not going to be able to get GC debug messages? Does that mean my only option is to use my device for a very long time and just make sure it never fails? Can I determine about how long a safe test length is?

Is there a simple program someone can think of that will show me the GC affecting execution without the debug messages?

Thank you all.

simplistically, the GC does as any GC does in modern computing - checks references to objects in memory, and cleans up those objects that are no longer referenced. Where the unknown comes in is where you may use a statement that causes underlying objects to be created and destroyed (strings and concatenation are a common offender). If you minimise the use of dynamically allocated buffers, minimise allocation in routines that get called often in preference to creating that as a global object and reusing it, then you can help minimise the need for GC to do massive work cleaning up memory. The GCs duration is directly related to how much cleaning up it needs to do, so the less you create and destroy, the shorter the impact. It will still run when you use these minimising practices but each pass through is quick and shouldn’t impact you.

As far as I can tell, there is no way for you to see any of the real impact of GC without seeing the debugging info that’s currently not enabled in G30/G80. You can force GC yourself in your code, and you can time how long that process takes, which is a reasonable measure, but the framework ordinarily shows this when it triggers GC. By forcing GC yourself you will negate some of the need for GC to run, which means you can try to be more strategic about when to run it, and that can actually be a permanent addition to your app.

@ jwizard93 - I missed your initial question. I’ve never had to do anything special to see the GC messages when I’m running a program in the debugger (with the USB cable connected). If I do something dumb like concatenation a lot of strings, I’ll see a fairly long set of GC lines show up in the output window of the debugger. You might try that, do something like concatenate a string in a long loop and see if the GC messages show up.

It was confirmed that on a G30/G80 the GC output messages aren’t coming thru. So no number of string functions will cause those messages to appear :slight_smile: