Hi All,
My colleagues and I had an issue with intermittent program crashes. We’ve been able to narrow it down to the garbage collector, by narrowing it down to a thrown out of memory exception and tracking our available memory. It appears that when the memory is low enough, garbage collection will automatically trigger. Over time, our managed memory drops to zero, is cleaned up, then begins counting down again. Occasionally, when garbage collection triggers, the entire program locks up.
Are there any known issues with particular types of method calls that interfere with garbage collection? None of the existing topics I could find were related to TinyCLR. Either GC enters an infinite loop or throws an exception that causes the entire program to crash.
Hi sgtyar95. We had similar issues with GC. Our program got locked after a while, apparently due to GC running when available memory was too low.
We solved that adding a thread that calls System.GC.GetTotalMemory(true); periodically. We also keep a track of available memory to fine tune the interval. Here is the code we use:
public static void Thread_GC()
{
long freeRAM;
while (true)
{
Thread.Sleep(P.WBOX.g_gctm); // P.WBOX.g_gctm: configurable interval, in milliseconds
// P.RAMfreeMIN keeps track of minimun available RAM (we can reset it whenever we want)
freeRAM = GHIElectronics.TinyCLR.Native.Memory.ManagedMemory.FreeBytes;
if (freeRAM < P.RAMfreeMIN) P.RAMfreeMIN = freeRAM;
// Call to GetTotalMemory method with wait for GC
System.GC.GetTotalMemory(true);
}
}
Hi jcplaza,
Thanks for the reply. This solution seems to be the consensus for now until we can figure out what the garbage collection is locking horns with - good to know that it works for you.
Thanks for your input. I’ll be on the lookout for things in the code that are constantly creating new objects. The way the application is designed utilizes a lot of static variables - we don’t do dynamic strings at all and instead use string libraries, all of our parameters and values are stored and manipulated using static libraries, etc. The memory still seems to be filling up very quickly. I am trying to go through the code to see if there is anything frequently called that creates objects, but it will take some time as the project is really large.
We have a variable shown on the LCD display indicating the current available memory. We can see when the GC occurs because the available memory is reset to 32mb. I occasionally get an ‘out of memory’ exception when the GC is running. Is there a chance that an event, timer or serial receive, would try to allocate memory during the GC. ? It seems to be at this time that the system hangs ?
Events can eat up memory. There is an internal queue for the event handler. Each event creates an entry for the queue. If you don’t process events fast enough, memory disappears into the queue.
I suppose a high event rate would also cause GC to occur.
We are currently doing garbage collection manually.(System.GC.GetTotalMemory(true) We monitor free memory and initiate GC when free memory is under 4MB. Occasionally, I still see out of memory exception. What would cause that ?
Doing GC manually does not guarantee that you will not run out of memory.
As I said earlier, manually invoking GC addresses the symptom, not the problem.
If you had 6MB of memory left, and requested 7MB you could get a memory exception.
Memory fragmentation could also cause an issue. That is when there appears to be enough memory, but not in a continuous piece to meet the allocation request.
The bottom line is you need to review and improve your use of memory. Continual GC is a red flag, with an unpredictable future.
Thanks for your help. I think I have determined that the GC procedure is not being interrupted. There must be an event queue that is processed in foreground.