G
Guest
I'm having issues with garbage collection with my long-standing service
process. If you could review and point me in the right direction it would be
of great help. If there are any helpful documents that you could point me to
help me control the GC, then that would be great also.
The .Net GC does not cleanup memory of our service process unless it is
forced to by another process that hogs memory.
· GC Algorithm - This is an issue because if the GC is not forced into doing
this, it does not aggressively cleanup until the amount of physical memory
available is very small. I understand why it doesn’t want to force cleanup
due to processor efficiency, but it forces applications into conditions that
are not acceptable. It would be nice to be able to hint an upper limit for
an application that helps the GC be more aggressive when required.
· Race Condition – The GC Algorithm causes race conditions because the GC is
not coordinated with our application and our application throws
OutOfMemoryExceptions. We have very good exception handling that guards
against unhandled exceptions in the main thread and thread pool threads. The
problem is that we use memory to log these issues so the handlers are
probably throwing another OutOfMemoryException. We can handle this, but the
point is the OutOfMemoryException cause a transaction to fail.
· Force GC To Collect - I wrote a Memory Hogger application which when run
will reduce the amount of memory used by the service application from 800MB
to 3MB, so this proves that the GC will cleanup the memory when it truly
needs it. I noticed that Memory Usage displayed in the Task Manager Process
tab did not add up to the total amount of memory in use, so this means that
the inactive applications probably moved their heap to swap. One concern
here was that when the Memory Hogger application was terminated, our service
application reclaimed half of its memory and we were not processing
transactions. Maybe GC just moved it to swap.
· GC.Collect – Using this is not recommended within the application. Even
when this is used, it doesn’t make the GC any more aggressive, so I agree,
there is no reason to use it. It would be nice to have the ability to make
the GC more aggressive.
· CLR Profiler - I’ve used the CLR Profiler to determine what memory is not
being collected. Mostly string and byte arrays. Our service handles TCP
Connections asynchronously and we reuse the same byte array when receiving
data for the next asynchronous read. We store a reference to the current
IAsyncResult for both the asynchronous send and receive requests. The state
object holds the byte array which we are currently not setting to null.
There isn’t a way of canceling the async requests, so we might have to
explicitly set this to null. I will try this to see if makes a difference.
As for the strings, I’m not sure where the problem is here.
process. If you could review and point me in the right direction it would be
of great help. If there are any helpful documents that you could point me to
help me control the GC, then that would be great also.
The .Net GC does not cleanup memory of our service process unless it is
forced to by another process that hogs memory.
· GC Algorithm - This is an issue because if the GC is not forced into doing
this, it does not aggressively cleanup until the amount of physical memory
available is very small. I understand why it doesn’t want to force cleanup
due to processor efficiency, but it forces applications into conditions that
are not acceptable. It would be nice to be able to hint an upper limit for
an application that helps the GC be more aggressive when required.
· Race Condition – The GC Algorithm causes race conditions because the GC is
not coordinated with our application and our application throws
OutOfMemoryExceptions. We have very good exception handling that guards
against unhandled exceptions in the main thread and thread pool threads. The
problem is that we use memory to log these issues so the handlers are
probably throwing another OutOfMemoryException. We can handle this, but the
point is the OutOfMemoryException cause a transaction to fail.
· Force GC To Collect - I wrote a Memory Hogger application which when run
will reduce the amount of memory used by the service application from 800MB
to 3MB, so this proves that the GC will cleanup the memory when it truly
needs it. I noticed that Memory Usage displayed in the Task Manager Process
tab did not add up to the total amount of memory in use, so this means that
the inactive applications probably moved their heap to swap. One concern
here was that when the Memory Hogger application was terminated, our service
application reclaimed half of its memory and we were not processing
transactions. Maybe GC just moved it to swap.
· GC.Collect – Using this is not recommended within the application. Even
when this is used, it doesn’t make the GC any more aggressive, so I agree,
there is no reason to use it. It would be nice to have the ability to make
the GC more aggressive.
· CLR Profiler - I’ve used the CLR Profiler to determine what memory is not
being collected. Mostly string and byte arrays. Our service handles TCP
Connections asynchronously and we reuse the same byte array when receiving
data for the next asynchronous read. We store a reference to the current
IAsyncResult for both the asynchronous send and receive requests. The state
object holds the byte array which we are currently not setting to null.
There isn’t a way of canceling the async requests, so we might have to
explicitly set this to null. I will try this to see if makes a difference.
As for the strings, I’m not sure where the problem is here.