Hi All,
After playing with the GC I find the following interesting. The problem domain I typically work in requires the allocation of very large arrays for image processing. We have discovered some issues when our processes are long running. We run out of memory and can not reclaim it. Our only recouse is to restart our processes. In an effort to discover why I uncovered the following: The LOH (Large Object Heap) is never compacted. I think this is a fatal flaw in the GC. I understand MS stated reason for this, but shouldn't there be someway to compact the LOH if necessary, at least a method call that forces the issue?
Does anyone know of anything that can be done? Any workaround is better than killing the process...
Here is a demo program that shines a very bright light on the issue. If anyone sees anything wrong with the logic please respond.
Here is a typical run's output:
Pass: 1 Array Size (MB): 0910 0910
Pass: 1 Max Array Size (MB): 0920 0000 System Out of Memory...
Pass: 2 Array Size (MB): 0910 0910
Pass: 2 Max Array Size (MB): 0920 0000 System Out of Memory...
Pass: 3 Array Size (MB): 0010 0010
Pass: 3 Max Array Size (MB): 0020 0000 System Out of Memory...
Pass: 4 Array Size (MB): 0010 0010
Pass: 4 Max Array Size (MB): 0020 0000 System Out of Memory...
Pass: 5 Array Size (MB): 0010 0010
Pass: 5 Max Array Size (MB): 0020 0000 System Out of Memory...
Press any key to exit...
As you can see by the time the program is finished with the LOH you can't even get 20 MB allocated !!!!
Here is the source code:
using System;
using System.Text;
using System.Threading;
namespace Burn_LOH
{
class Program
{
static void Main (string[] args)
{
for (int count = 1; count <= 5; ++count)
AllocBigMemoryBlock (count);
Console.Write ("\nPress any key to exit...");
while (Console.KeyAvailable == false)
Thread.Sleep (250);
}
static void AllocBigMemoryBlock (int pass)
{
const int MB = 1024 * 1024;
byte[] array = null;
long maxmem = 0;
int arraySize = 0;
GC.Collect ();
GC.WaitForPendingFinalizers ();
while (true)
{
try
{
arraySize += 10;
array = new byte[arraySize * MB];
array[arraySize * MB - 1] = 100;
GC.Collect ();
GC.WaitForPendingFinalizers ();
maxmem = GC.GetTotalMemory (true);
Console.Write ("Pass: {0} Array Size (MB): {1:D4} {2:D4}\r", pass, arraySize, Convert.ToInt32 (maxmem / MB));
}
catch (System.OutOfMemoryException)
{
GC.Collect ();
GC.WaitForPendingFinalizers ();
maxmem = GC.GetTotalMemory (true);
Console.Write ("\n");
Console.Write ("Pass: {0} Max Array Size (MB): {1:D4} {2:D4} {3}\r\n\n", pass, arraySize, Convert.ToInt32 (maxmem / MB), "System Out of Memory...");
break;
}
finally
{
array = null;
GC.Collect ();
GC.WaitForPendingFinalizers ();
}
}
}
}
}