Main Site Documentation

Debug.GC() freeze/reboot


#1

I have the same behavior as described here
https://www.ghielectronics.com/community/forum/topic?id=9876
and here
https://www.ghielectronics.com/community/forum/topic?id=10221
with FW 4.2.11.1 on all tested G120 (custom boards)

But test programs from both mentioned threads work fine.
My app is quite memory consuming (uses about half of RAM, just about 3MByte are free).
It’s also using a couple of open Network connections (TCP/IP server and client), but it should be good under the maximum limit.
There are also a couple waiting (Manual)ResetEvent’s waiting in different threads.
In my test environment no network cable is connected.
Wenn a cable is connected (with some traffic from external source) some of the Debug.GC calls does not cause a freeze/reboot.

I can not remember that this happened with 4.2.11.0, but my project has grown since. I also thought that I did not have this problem at the beginning with 4.2.11.1, but at least my stability problems started shortly after the update.

If the GC runs on it’s own there is no freeze/reboot (happens every time when my data is initialized). No matter if I put a Debug.GC before or after that it will freeze/reboot.

This is a critical issue for me, because this should already run at a customer site.
Any hint is really appreciated.

I’ll play around with my program and the test program and will provide more info if I can find out more.

I got one more info on this.
Debug.GC freezes/reboots after allocating a lot of small objects (classes).
“A lot of” means thousands.
Allocating them is fine, using them is fine, but GC can not handle it!?
The objects are organized as a linked list (each one has a reference to the next one (but not back). I thought this would be better than an ArrayList (which causes an outofMemory exception, even that there is plenty free RAM). Can’t use a static array b/c I don’t know how many items I get when I start reading the file.


#2

Consider reusing objects instead of continually allocating new ones. Keep a linked list of freed objects and only allocate new ones when free list is empty.


#3

I do not release these objects. They are all needed at runtime.


#4

I managed to reproduce my issue in a small program:
You can download the sample Project here:
http://www.aarpg.net/GcRebootTest.zip
The project is for VS2012.

You need a SD Card and where you place the 3 files ifrom the SD folder in the root of the SD card.

It does not matter if I load the files in a different order or if I load the same file twice.
It always fails at the GC after the 2nd file.

I’m using
G120 (custom board)
SD card

I will test on my G120HDR as well when I’m back home.

If someone could test with 4.2.11.0 as well this would be great. It’s always a pain to switch SDK.


#5

@ Reinhard Ostermeier - I tested your original code on a Cobra II and see same behavior as you described. Then i did some cleanup using resharper and it seems to make a difference. If you want to share your mail address i can sent you the modified file “program.cs” Maybe by comparing the sources you can see what made the difference.


#6

@ RobvanSchelven - Thank you, you can send it to ‘osre at aarpg dot net’.
I think this problem is a bit code sensitive.

Even if optimized code will avoid the problem it’s stil there, no matter what code you run. As long as several MByte of RAM are available CG should work.


#7

@ Reinhard Ostermeier - I send the file, but I do agree with you. If it can be used for now as a work around you might be able to satisfy your customer :slight_smile:


#8

@ RobvanSchelven - I think ReSharper removed the class var for the linked list root. By this none of the thousends of objects are referenced, so GC can collect them.
In fact this makes the whole program useless.
The reason why ReSharper did this is that I commented the code which uses it to avoid adding more code to the program, which is not related to the Problem.

Would have been to nice :frowning:


#9

@ Reinhard Ostermeier - I get it, unfortunately :frowning:


#10

I have stripped down the code to the absolute minimum:

using System.Threading;
using Microsoft.SPOT;

namespace GcRebootTest
{
   public class Program
   {
      public static void Main()
      {
         // give debugger a chance to attach in endles reboot loop
         Thread.Sleep(5000);

         var loader1 = new Loader();
         loader1.CreateSome();
         // this GC is always ok
         Debug.GC(true);

         var loader2 = new Loader();
         loader2.CreateSome();
         // this GC always freezes/reboots
         Debug.GC(true);

         // we never get here
         Thread.Sleep(5000);
      }
   }

   public class Loader
   {
      public void CreateSome()
      {
         _First = null;
         KmaParam last = null;

         // it doesn't matter if i create 200 or 5000 items per linked list, GC always fails after 2nd list is created!
         // at 130 the 2nd GC is OK, at 140 it fails
         for (int n = 0; n < 200; ++n)
         {
            var param = new KmaParam();

            if (last == null)
            {
               _First = param;
            }
            else
            {
               last.Next = param;
            }
            last = param;
         }
      }
      private KmaParam _First;
   }

   internal class KmaParam
   {
      internal KmaParam Next;

      // if field is removed then GC does not freeze/reboot !?
      public int TelegramNo;
   }
}

No SD card, external files to read or complex objects are involved anymore.
It looks like as if GC has a huge problems with linked lists :frowning:
Also memory usage is way down in this sample, so this is not the reason I think
Would really be nice if GHI could look into this.


#11

FYI The behavior is seen also in the emulator.


#12

Confirmed.
Happens also with 4.3 in Emulator.
So GHI seams to be of the hook.
By by linked lists :wall:

Anyway, would be nice if anyone with some insight into the runtime could comment this.


#13

@ Reinhard Ostermeier -

Something wrong with NETMF?


#14

@ Dat - Jep
I have a lot of small objects. I create them by reading a file from SD.
I don’t know how many I’ll get.
So I used an ArrayList at first.
Then IO got an OutOfMemory exception. Looks like every object reference in ArrayList needs 12 Bytes.
So I made it a linked list.
But GC can not handle a linked list in memory.
Any Ideas how to do this.
I thought of an ArrayList which contains arrays of my objects.


#15

With thousands of objects GC might be running out of memory. Might be due to the way GC determines if objects are still being referenced. Recursion might be used, resulting in memory overflow. Time to look at the code in the porting kit.

Might be worth while to chain blocks, each containing multiple objects, resulting in a shorter chain.

You might want to try to increase the capacity of an ArrayList right after creation to the maximum number of object to be supported. Will avoid memory issues due to dynamically increasing the capacity of the ArrayList.


#16

@ Reinhard Ostermeier - When you use ArrayList, remember that .NETMF has a limit of +/-700KB (closer to 800 actually) for a single allocation and an array is a single allocation.

Internally ArrayList has a object[] so the total number of elements in the array should not exceed the 700KB limit otherwise you will get an allocation failure even though you have more than enough memory.

Fortunately they array is an array of references so you should be able to get about 60,000 - 65,000 element object[], that is of course disregarding the size of the actual elements which will not be counted towards the single allocation limit, but will of course consume main memory.

For example, assuming you have an ArrayList called values and one of the devices with lots of memory like the Spider, G400, Raptor, Hydra etc.

This will work (can probably get a little more than 65000) at around 760KB


values = new ArrayList();
values.Capacity = 65000;

But this will fail with an OutOfMemoryException even though there is actually plenty of memory.


values = new ArrayList();
values.Capacity = 67000;

I used capacity in the sample above, the same applies if you just let the array list dynamically grow.


#17

Even there is a good explanation of why it might happen i think a reboot or lockup is unacceptable. at least an exception is expected.


#18

Multiple linked lists are not the solution.
My tests showed for that a single list with 5000 elements is no problem.
But two lists with 200 elements each GC will freeze.


#19

@ taylorza - I’m aware of the Capacity property, but it’s hard to set it if you don’t know how many items you well get in advance (don’t want to loose too much RAM.
In my case it caused a OutOfMemoryExeption on add telling me: (numbers are not exact)
"Allocating 2748 Block: 33000 Bytes"
This means to me: ArrayList wanted to allocate an array of 2748 elements, which would use 33000 Bytes.
By this each element (object reference) uses 12 Bytes.
What I don’t understand here is that 33k is less then half of the limit, And I had 3MByte available RAM. So it must be fragmentation which caused that exception.


#20

Since it also happens in Emulator I have reported it on codeplex as well: