all groups > dotnet clr > may 2005 >
You're in the

dotnet clr

group:

Garbage Collection - Strange Results.


Garbage Collection - Strange Results. CodeGuru
5/14/2005 2:54:08 PM
dotnet clr:
Althought I have read hundreds if not more pages on
msdn as well other sites on IDisposable and heap
generations. I am still a bit confused as to why
the application I have written is acting in such
"weird/awkward" manner.

Basic outline of the application goes:

Multi threaded socket application using Asynchronous
writes/reads/connects via TCP Sockets.

I have written an application that starts 100 threads
and attaches 10 sockets from a peer to each of these
threads; thus 1000 active sockets open.

Now. the application runs fine; I calculate using ANTS profiler
or any other profiling utility and it tells me that I have approximately
30 MB of Memory used.

I call GC.GetTotalMemory(false) or even (true) and it gives me approximately
the same values depending what stage of processing each thread
is at.

All threads are doing the same thing by the way.

When I look in Windows Performance Monitor and under .NET Memory
for that particular application the memory seems to be quite high.

Several Hundred MEGABYTES.

The application runs over time.. slowly but surely increasing in memory.
as the threads complete their tasks with the sockets it closes them.
and Disposes each and every object. I explicitly set each object to null
as well its children.. and have inherited IDisposable on almost all
objects.

What I don't understand is why the memory keeps increasing,
while the application keeps reporting only 30MB of usage... the memory
keeps increasing and increasing until the system runs out of Physical Memory
and causes OutOfMemoryExpections.... its quite strange. I am not doing
anything within the application that would create anything larger then it
should.

However I do thousands of XmlSerializations using a single MemoryStream
for each socket that is created; there are thousands of Asychronous callbacks
that are happening.

My Generation 0 and 1 heaps seem to be doing just fine.. but 2nd gen heap
seems to be at hundreds of megs; its very strange to see this.

I assumed that the .NET GC will keep on expanding the space required until
it is ready for a garbage collection.. would it be because of the magnitute of
ArrayLists that I am using ? or perhaps there are scattered memory segments.
throughout the Heaps ? is the GC having a difficult time collecting all the
resources?

Any help on why this is occuring would be appreciated.

I have tried my best to clean up all the resources.. but I figure that
most of the objects created should automatically get cleaned up
after it is out of the final scope that it is passed to.. for example.
once a command comes in via the Async Read Callback, I process it
and pass it to the appropriate thread DataReceive method.
I not only dispose the object within CallBack but I also dispose
the reference that was passed again just incase..

doesn't seem to be doing anything .. and what is even more strange
is why is .NET or all Profilers such as ANTS .NET profiler report
that I am only using 30MB of memory ? when in Task Manager
or Performance Monitor I see hundreds of megs like 600+.

Re: Garbage Collection - Strange Results. Willy Denoyette [MVP]
5/15/2005 12:00:00 AM

[quoted text, click to view]

1. Don't use taskman, use perfmon and the "CLR Memory" counters Gen0, 1 and
2 size to watch managed memory consumption.
2. Take a look at the # of pinned objects using perfmon (CLR memory
counters).
3. Use perfmon to watch your "process" privates bytes.

If the the Gen 2 counter indicates a steady growth and the number of pinned
objects is rather high (> 100) chances are that pinned objects are aging
into Gen2 and as such preventing compactation of the heap.
If that's the case you are probably holding references to socket
(read/write) buffers for the lifetime of the socket.

I would also suggest you to reduce the number of threads, 100 threads is
only a waste of resources (both memory and CPU) when using asynchronous
sockets.

Willy.



Re: Garbage Collection - Strange Results. Arnaud Debaene
5/16/2005 8:15:54 AM
[quoted text, click to view]
Just a guess if you're using asynchronous calls : Do you call EndInvoke for
each BeginInvoke on a delegate? Failing to do so would result in memory
leak...

Arnaud
MVP - VC

RE: Garbage Collection - Strange Results. Ravichandran J.V.
5/17/2005 12:21:02 AM
To start with, I think you are just too anxious. If you have read MSDN, there
is an article that explains that the .Net GC is based on a liberal algorithm
(mark and remove). This algorithm works on a stupid belief that the memory in
the system is infinite.

Because memory management is automatic in the CLR, the GC needs some way to
determine which objects can be collected and which not. To help GC determine
disposable objects, it is instructed that all objects in an idle state or
which are no longer referenced by any application can be safely considered as
disposable objects.

But, because the managed heap is made up of contiguous memory locations,
those objects which have been removed from memory would leave a void in
between causing performance leaks for applications that require faster object
allocation, the GC is also told to compact these void areas so as to maintain
contiguity for enabling faster access to free memory for allocating new
objects to memory. Another important aspect of how the managed heap is
managed by the GC is through the generations. Usually, the managed memory is
divided into three generations - 0,1,2. Generation 0 is considered to be the
critical area for the GC. It has been instructed always to look up Gen 0 and
if memory is critical in this generation then it is instructed to move all
old objects to the subsequent generation to make room for fresh objects. This
movement of objects is called promotion of objects. But this promotion
happens only if there is a collection in a particular generation. For
example, if you execute a statement GC.Collect(0) then when GC is invoked a
collect will be performed on Generation 0 causing older objects to be moved
from gen 0 to 1. If you perform another collection with GC.Collect(1) then
objects from Gen 1 will be moved to Gen 2.

But, this is where you are seeking info, since there is no more generation,
the Gen 2 will keep expanding until the system is out of memory and an
OutOfMemoryException is thrown.

Instead of Ants and the other tools that you are using, I suggest you use
the CLR Profiler (search on clrprofiler.exe free download on Google) which
provides you with a Heap Dump through which you can get many perspectives
into how the CLR is managing memory within.

with regards,

J.V.




[quoted text, click to view]
RE: Garbage Collection - Strange Results. CodeGuru
5/18/2005 6:37:26 AM
Ravichandran,

Thanks for the info, I know of how generations work; but regardless
still useful information. A question I have is when looking at performance
monitor I noticed hundreds if not thousands of objects being pinned,
my point being is why would objects get pinned in the first place ?
is it because perhaps it is being access by the system ? perhaps
there is a lock on the object ? would locked objects cause the GC
to pin the object and not be able to compact the Heap ?

I haven't been able to find proper documentation on the different
reasons why objects would get pinned.

All in all, it seems by looking at the CLR Profiler that there is many
voids (empty spaces) in the memory is this normal ?

I also noticed the TOTAL HEAP SIZE of my application remainds between
500 to 600 MB and never expands more then that.. which is a good thing.
but ! there is always a but.. when looking at the WORKINGSET
it seems to be expanding and expanding.. also when looking at Task Manager
the MEM USAGE is always stable yet the VM SIZE keeps growing ?
the total available memory seems to be keep growing until I minimize the
window?
once doing so, the memory drastically grows from 200 MB to 800 to 900 MB of
free space ?

Would Console.WriteLine calls perhaps have a buffer problem ?
or perhaps using Reflections to reflect and create objects in thousands
per second cause a memory problem ?

The communication layer in my application uses reflections to grab the root
xml node and create an object based on that name and deserialize it, I
wonder if this could perhaps also be a cause of this problem ?

I am still looking at the CLR its a bit hard to follow, but nevertheless
useful.

Thank you for the info


Kaz


[quoted text, click to view]
Re: Garbage Collection - Strange Results. CodeGuru
5/18/2005 1:48:06 PM
Willy,

Thanks for the info, now that you mention it, and reviewing your posting
for a second time, I noticed something you mentioned !! that could
possibly .. maybe be a serious problem !

you said "I am holding onto buffers in my read / write" when infact
and indeed I am.. I have created a private member for each socket
that has a Buffer for reading and a ObjectBuffer for completing.
once a full object has been completed I copy it to a completed buffer
and execute a Reflection on it to "create" the actual object from
the serialization stream (socket) more over, the object buffer never
really gets destroyed unless the socket is killed.. so perhaps your
telling me that because I have these infact may be the pinned objects?
in my application ?

Also: pinned object in performance monitor shows drastic values;
it goes anywhere between 0 to 2000 pinned objects on each update.


Private Bytes in Process shows over 300 MB for Active 500 Sockets...
and 50 threads.


Kaz


[quoted text, click to view]
RE: Garbage Collection - Strange Results. Ravichandran J.V.
5/18/2005 10:18:04 PM
<quote>I haven't been able to find proper documentation on the different
reasons why objects would get pinned.</quote>

Objects would get pinned while, as you have surmised, they have been locked;
they would get pinned if the object is being used by an unmanaged app or
object; they would get pinned if you use the fixed expression to pin unsafe
code.

[quoted text, click to view]

Windows uses upto 4 GB of virtual memory according to my coleague who is a
MCSE.

with regards,

J.v.


[quoted text, click to view]
Re: Garbage Collection - Strange Results. Phil Wilson
5/20/2005 12:10:13 PM
A couple of sanity-check questions:
1. You're not running Debug builds are you?
2. Have you turned on the Server framework with COMPLUS_BUILDFLAVOR or
something?
--
Phil Wilson [MVP Windows Installer]
----
[quoted text, click to view]
Re: Garbage Collection - Strange Results. CodeGuru
5/20/2005 1:50:03 PM
Phil,

I have ran in both Debug and Release, same results and
no I haven't turned on COMPLUS_BUILDFLAVOR, how would
go about doing this (sorry for the ignorance) ?

Using VS 2003.

Thanks

Kaz

[quoted text, click to view]
RE: Garbage Collection - Strange Results. Ravichandran J.V.
5/21/2005 12:54:02 AM
<quote> and create objects in thousands per second cause a memory problem
</quote>

Memory problems do not arise in the managed environment due to numerous
objects but due to numerous GC collections. Get a view of the number of GC
collections on a generation in the CLR Profiler. More the collections on a
generation, more you should think about how objects are being used by your
app.

with regards,

J.V.


[quoted text, click to view]
AddThis Social Bookmark Button