Does this code Force Garbage Collector to Collect

  • Thread starter Thread starter LP
  • Start date Start date
L

LP

Hi,
Considering code below. Will it make GC to actually collect. One application
creates new instances of a class from 3rd party assembly in a loop (it has
to). That class doesn't have .Dispose or any similar method. I want to make
sure GC keeps up with the loop. My reasoning if Thread.Sleep(1000) is
called; GC will take priority it do its work, right?

GC.Collect();
GC.WaitForPendingFinalizers();
System.Threading.Thread.Sleep(1000);
 
LP,
It does, however you may be hurting the GC's ability to "do a good job",
rather then helping it.

For details see Rule #1 at:

Just remember that "the collector is self-tuning so don't mess with it"!

Hope this helps
Jay
 
LP,

The GC will keep up with object allocations, and collect them when it
requires. Like Jay stated, the GC is self-tuning based on your allocation
pattern, so it will find the best time to collect by itself.

Why do you feel you need to force garbage collections?

-Chris

--------------------

|
| LP,
| It does, however you may be hurting the GC's ability to "do a good job",
| rather then helping it.
|
| For details see Rule #1 at:
|
| >> http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx
| >> http://blogs.msdn.com/ricom/archive/2003/12/02/40780.aspx
|
| Just remember that "the collector is self-tuning so don't mess with it"!
|
| Hope this helps
| Jay
|
| | > Hi,
| > Considering code below. Will it make GC to actually collect. One
| > application
| > creates new instances of a class from 3rd party assembly in a loop (it
has
| > to). That class doesn't have .Dispose or any similar method. I want to
| > make
| > sure GC keeps up with the loop. My reasoning if Thread.Sleep(1000) is
| > called; GC will take priority it do its work, right?
| >
| > GC.Collect();
| > GC.WaitForPendingFinalizers();
| > System.Threading.Thread.Sleep(1000);
| >
| >
| >
|
|
|
 
Why do you feel you need to force garbage collections?
As stated before there is a loop creating new instances of a 3rd party
object each instances does some processing and outputs data to a report file
in PDF format. We tried having to work with one instance in the loop, but it
just screws up the formatting of the reports, it's pretty obvious it needs a
separate instance per report file.
As of now this program creates over 100 PDFs, it's possible that eventually
there will be much more, perhaps thousands. Performance of this application
is not a critical issue, since it's a batch process style app which runs on
scheduled basis.
So, We're Just trying to avoid potential memory problems (out of Memory
exceptions); we have seen a fair share of those.
 
Is this a .Net object? If so, if it is holding on to resources, it should
expose a Dispose method. If it is a COM object, are you calling
Marshal.Release to reduce the reference count once you have finished with it?

Dan

LP said:
Why do you feel you need to force garbage collections?
As stated before there is a loop creating new instances of a 3rd party
object each instances does some processing and outputs data to a report file
in PDF format. We tried having to work with one instance in the loop, but it
just screws up the formatting of the reports, it's pretty obvious it needs a
separate instance per report file.
As of now this program creates over 100 PDFs, it's possible that eventually
there will be much more, perhaps thousands. Performance of this application
is not a critical issue, since it's a batch process style app which runs on
scheduled basis.
So, We're Just trying to avoid potential memory problems (out of Memory
exceptions); we have seen a fair share of those.


"Chris Lyon [MSFT]" said:
LP,

The GC will keep up with object allocations, and collect them when it
requires. Like Jay stated, the GC is self-tuning based on your allocation
pattern, so it will find the best time to collect by itself.

Why do you feel you need to force garbage collections?

-Chris

--------------------

|
| LP,
| It does, however you may be hurting the GC's ability to "do a good job",
| rather then helping it.
|
| For details see Rule #1 at:
|
| >> http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx
| >> http://blogs.msdn.com/ricom/archive/2003/12/02/40780.aspx
|
| Just remember that "the collector is self-tuning so don't mess with it"!
|
| Hope this helps
| Jay
|
| | > Hi,
| > Considering code below. Will it make GC to actually collect. One
| > application
| > creates new instances of a class from 3rd party assembly in a loop (it
has
| > to). That class doesn't have .Dispose or any similar method. I want to
| > make
| > sure GC keeps up with the loop. My reasoning if Thread.Sleep(1000) is
| > called; GC will take priority it do its work, right?
| >
| > GC.Collect();
| > GC.WaitForPendingFinalizers();
| > System.Threading.Thread.Sleep(1000);
| >
| >
| >
|
|
|
 
Considering code below. Will it make GC to actually collect. One
application
creates new instances of a class from 3rd party assembly in a loop (it has
to). That class doesn't have .Dispose or any similar method. I want to
make
sure GC keeps up with the loop. My reasoning if Thread.Sleep(1000) is
called; GC will take priority it do its work, right?

GC.Collect();
GC.WaitForPendingFinalizers();
System.Threading.Thread.Sleep(1000);

While I agree with everyone else that calling GC.Collect() isn't a good
idea, your call to Thread.Sleep isn't needed here. The GC activates on the
call to GC.Collect and WaitForPendingFinalizers() waits while finalizers are
executed and the finalizer queue cleared(however I don't know that it
ensures that those finalized object graphs are GC'd or not, that would
likely be much more important a question). By the time you are reaching the
sleep statement the garbage collection is complete.
 
Is this a .Net object? If so, if it is holding on to resources, it should
expose a Dispose method. If it is a COM object, are you calling
Marshal.Release to reduce the reference count once you have finished with
it?

Yes, it's a .NET object, but no unfortunately it doesn't expose .Dispose
method .
idea, your call to Thread.Sleep isn't needed here. The GC activates on the
call to GC.Collect and WaitForPendingFinalizers() waits while finalizes are
executed
I don't think it's true. GC runs on a separate thread with a priority lower
than a main thread. Calling GC.collect() doesn't guarantee that GC will
start right away, it's my understanding you're telling runtime to increase
priority of GC, but when it will actually be executed depends on what is
currently running and/or scheduled to run, after runtime executes important
tasks; then maybe GC.collect() is scheduled to execute or maybe not. Calling
GC.Collect() is like kindly suggesting to runtime, maybe you should start
thinking about garbage collection, but when it will do is unknown.
Thread.Sleep() will stop current thread and give way to other scheduled task
to execute which will hopefully be GC.collect (again it's not 100%, but much
better chances)
I've seen enough arguments that GC is optimized to do its job when needed.
So I think it makes sense to comment out GC.Collect() , and monitor memory
usage.... I hope it will become more obvious if it's needed or not over
time.
 
LP,

Marina (regular to dotnet newsgroups) had about a year ago a problem with a
routine that had strange behaviour and memory.

Setting a "label.show" in here routine that we tried, started the GC. A kind
as if when the paint was given to the graphic adapter, the GC was doing its
job.

From that time I am not interested in it anymore because its behaviour
however have the idea that it is well done.

Cor
 
From that time I am not interested in it anymore because its behaviour
however have the idea that it is well done.

From that time I am not interested anymore when it is working, because thiss
behaviour gave me the idea that it was well done.
 
I would recommend against early memory/perf optimizations. It's best to
measure where the bottlenecks are and address them, than trying to do early
fixes which may cause other issues. Your GC.Collect loop, for example,
will cause early promotion of objects that would otherwise be considered
garbage. This will result in less memory being freed.

Rico Mariani has a great blog about performance, and talks a lot about the
GC:
http://blogs.msdn.com/ricom

In particular, I recommend:
http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx
http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx
http://channel9.msdn.com/wiki/default.aspx/Channel9.RicoM

Hope that helps
-Chris

--------------------

|
| > Why do you feel you need to force garbage collections?
| As stated before there is a loop creating new instances of a 3rd party
| object each instances does some processing and outputs data to a report
file
| in PDF format. We tried having to work with one instance in the loop, but
it
| just screws up the formatting of the reports, it's pretty obvious it
needs a
| separate instance per report file.
| As of now this program creates over 100 PDFs, it's possible that
eventually
| there will be much more, perhaps thousands. Performance of this
application
| is not a critical issue, since it's a batch process style app which runs
on
| scheduled basis.
| So, We're Just trying to avoid potential memory problems (out of Memory
| exceptions); we have seen a fair share of those.
|
|
| | > LP,
| >
| > The GC will keep up with object allocations, and collect them when it
| > requires. Like Jay stated, the GC is self-tuning based on your
allocation
| > pattern, so it will find the best time to collect by itself.
| >
| > Why do you feel you need to force garbage collections?
| >
| > -Chris
| >
| > --------------------
| >
| > |
| > | LP,
| > | It does, however you may be hurting the GC's ability to "do a good
job",
| > | rather then helping it.
| > |
| > | For details see Rule #1 at:
| > |
| > | >> http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx
| > | >> http://blogs.msdn.com/ricom/archive/2003/12/02/40780.aspx
| > |
| > | Just remember that "the collector is self-tuning so don't mess with
it"!
| > |
| > | Hope this helps
| > | Jay
| > |
| > | | > | > Hi,
| > | > Considering code below. Will it make GC to actually collect. One
| > | > application
| > | > creates new instances of a class from 3rd party assembly in a loop
(it
| > has
| > | > to). That class doesn't have .Dispose or any similar method. I want
to
| > | > make
| > | > sure GC keeps up with the loop. My reasoning if Thread.Sleep(1000)
is
| > | > called; GC will take priority it do its work, right?
| > | >
| > | > GC.Collect();
| > | > GC.WaitForPendingFinalizers();
| > | > System.Threading.Thread.Sleep(1000);
| > | >
| > | >
| > | >
| > |
| > |
| > |
| >
|
|
|
 
LP said:
it?

Yes, it's a .NET object, but no unfortunately it doesn't expose .Dispose
method .

I don't think it's true. GC runs on a separate thread with a priority
lower
than a main thread. Calling GC.collect() doesn't guarantee that GC will
start right away, it's my understanding you're telling runtime to increase
priority of GC, but when it will actually be executed depends on what is
currently running and/or scheduled to run, after runtime executes
important
tasks; then maybe GC.collect() is scheduled to execute or maybe not.
Calling
GC.Collect() is like kindly suggesting to runtime, maybe you should start
thinking about garbage collection, but when it will do is unknown.
Thread.Sleep() will stop current thread and give way to other scheduled
task
to execute which will hopefully be GC.collect (again it's not 100%, but
much
better chances)
I've seen enough arguments that GC is optimized to do its job when needed.
So I think it makes sense to comment out GC.Collect() , and monitor memory
usage.... I hope it will become more obvious if it's needed or not over
time.

The GC runs on a user's thread, not on a separate thread. Note that when the
GC runs all managed threads are suspended. The finalizer runs on a separate
thread and runs with a higher priority than normal.
The GC is activated when a certain managed heap threshold is reached, this
threashold depends on the size of the level 2 cache and is dynamically
adjusted according the usage pattern.
Calling GC.Collect will directly initiate a GC run, it's not like kindly
suggesting.

Willy,
 
Willy

A couple of corrections to your post:

|Note that when the GC runs all managed threads are suspended.

This is not true for Concurrent collections. See
http://blogs.msdn.com/clyon/archive/2004/09/08/226981.aspx.

| The GC is activated when a certain managed heap threshold is reached,

A collection can occur if an allocation fails, if memory pressure hits a
certain threshold, if the user induces a collection, and on appdomain
unloads, and various other scenarios.

| this threashold depends on the size of the level 2 cache and is
dynamically
| adjusted according the usage pattern.

As I stated above, the GC uses a variety of criteria to determine when to
collect. Your statement about level 2 cache isn't correct, although the GC
will tune itself based on allocation patterns. Users should not use L2
cache as indication of when the GC will perform a collection.

Hope that helps

-Chris

--------------------
|
|
| | >> Is this a .Net object? If so, if it is holding on to resources, it
should
| >> expose a Dispose method. If it is a COM object, are you calling
| >> Marshal.Release to reduce the reference count once you have finished
with
| > it?
| >
| > Yes, it's a .NET object, but no unfortunately it doesn't expose .Dispose
| > method .
| >
| >> idea, your call to Thread.Sleep isn't needed here. The GC activates on
| >> the
| >> call to GC.Collect and WaitForPendingFinalizers() waits while finalizes
| > are
| >> executed
| > I don't think it's true. GC runs on a separate thread with a priority
| > lower
| > than a main thread. Calling GC.collect() doesn't guarantee that GC will
| > start right away, it's my understanding you're telling runtime to
increase
| > priority of GC, but when it will actually be executed depends on what is
| > currently running and/or scheduled to run, after runtime executes
| > important
| > tasks; then maybe GC.collect() is scheduled to execute or maybe not.
| > Calling
| > GC.Collect() is like kindly suggesting to runtime, maybe you should
start
| > thinking about garbage collection, but when it will do is unknown.
| > Thread.Sleep() will stop current thread and give way to other scheduled
| > task
| > to execute which will hopefully be GC.collect (again it's not 100%, but
| > much
| > better chances)
| > I've seen enough arguments that GC is optimized to do its job when
needed.
| > So I think it makes sense to comment out GC.Collect() , and monitor
memory
| > usage.... I hope it will become more obvious if it's needed or not over
| > time.
| >
|
| The GC runs on a user's thread, not on a separate thread. Note that when
the
| GC runs all managed threads are suspended. The finalizer runs on a
separate
| thread and runs with a higher priority than normal.
| The GC is activated when a certain managed heap threshold is reached,
this
| threashold depends on the size of the level 2 cache and is dynamically
| adjusted according the usage pattern.
| Calling GC.Collect will directly initiate a GC run, it's not like kindly
| suggesting.
|
| Willy,
|
|
|
|
 
Chris,

See inline ***

Willy.

"Chris Lyon [MSFT]" said:
Willy

A couple of corrections to your post:

|Note that when the GC runs all managed threads are suspended.

This is not true for Concurrent collections. See
http://blogs.msdn.com/clyon/archive/2004/09/08/226981.aspx.
*** I thought the difference between concurrent GC and non-concurrent GC was
that the former suspends the managed threads a few times for a short period
of time during a full (Gen2) collection, while the non-concurent flavor
suspends all threads (by calling SuspendEE) for the full duration of the GC,
calling RestartEE when done. I also thought that for a Gen0 or Gen1
collection there is no difference between the flavors, that means all
threads are suspended for the duration of the GC run.
So it was my understanding the whenever the GC effectively runs, be it for a
short period during full collects or for the whole collection, all managed
threads were suspended. Am I realy that wrong?
If I'm wrong, would'nt it mean the GC runs on a dedicated thread? Honestly I
never noticed this.
| The GC is activated when a certain managed heap threshold is reached,

A collection can occur if an allocation fails, if memory pressure hits a
certain threshold, if the user induces a collection, and on appdomain
unloads, and various other scenarios.
*** I know there are more criteria to trigger a collection, and the Gen
thresholds are only one of them.
| this threashold depends on the size of the level 2 cache and is
dynamically
| adjusted according the usage pattern.

As I stated above, the GC uses a variety of criteria to determine when to
collect. Your statement about level 2 cache isn't correct, although the
GC
will tune itself based on allocation patterns. Users should not use L2
cache as indication of when the GC will perform a collection.

*** I know there are more heuristics to determine the Gen0 heap size, but
according codepremium [1] the L2 cache size is one the parameters used to
set the initial size of the Gen0.

[1]
/codepremium/source/windows server 2003/winsrvr03 sp1
rc1(1289)/com/netfx/src/clr/vm/gcport.cpp
 
I am learning a lot about GC from this discussions and links provided in
this thread. Thank you all.
I do have one more question; how can I monitor *real time* when GC starts
running and what thread. In general how one monitors what application is
doing what threads are running, how much memory is consumed, etc.
Do you use some kind of special tool?


Willy Denoyette said:
Chris,

See inline ***

Willy.

"Chris Lyon [MSFT]" said:
Willy

A couple of corrections to your post:

|Note that when the GC runs all managed threads are suspended.

This is not true for Concurrent collections. See
http://blogs.msdn.com/clyon/archive/2004/09/08/226981.aspx.
*** I thought the difference between concurrent GC and non-concurrent GC was
that the former suspends the managed threads a few times for a short period
of time during a full (Gen2) collection, while the non-concurent flavor
suspends all threads (by calling SuspendEE) for the full duration of the GC,
calling RestartEE when done. I also thought that for a Gen0 or Gen1
collection there is no difference between the flavors, that means all
threads are suspended for the duration of the GC run.
So it was my understanding the whenever the GC effectively runs, be it for a
short period during full collects or for the whole collection, all managed
threads were suspended. Am I realy that wrong?
If I'm wrong, would'nt it mean the GC runs on a dedicated thread? Honestly I
never noticed this.
| The GC is activated when a certain managed heap threshold is reached,

A collection can occur if an allocation fails, if memory pressure hits a
certain threshold, if the user induces a collection, and on appdomain
unloads, and various other scenarios.
*** I know there are more criteria to trigger a collection, and the Gen
thresholds are only one of them.
| this threashold depends on the size of the level 2 cache and is
dynamically
| adjusted according the usage pattern.

As I stated above, the GC uses a variety of criteria to determine when to
collect. Your statement about level 2 cache isn't correct, although the
GC
will tune itself based on allocation patterns. Users should not use L2
cache as indication of when the GC will perform a collection.

*** I know there are more heuristics to determine the Gen0 heap size, but
according codepremium [1] the L2 cache size is one the parameters used to
set the initial size of the Gen0.

[1]
/codepremium/source/windows server 2003/winsrvr03 sp1
rc1(1289)/com/netfx/src/clr/vm/gcport.cpp
 
Hi Willy

--------------------
| *** I thought the difference between concurrent GC and non-concurrent GC
was
| that the former suspends the managed threads a few times for a short
period
| of time during a full (Gen2) collection, while the non-concurent flavor
| suspends all threads (by calling SuspendEE) for the full duration of the
GC,
| calling RestartEE when done. I also thought that for a Gen0 or Gen1
| collection there is no difference between the flavors, that means all
| threads are suspended for the duration of the GC run.
| So it was my understanding the whenever the GC effectively runs, be it
for a
| short period during full collects or for the whole collection, all
managed
| threads were suspended. Am I realy that wrong?
| If I'm wrong, would'nt it mean the GC runs on a dedicated thread?
Honestly I
| never noticed this.

No, the GC doesn't have a dedicated thread, sorry if I implied that.
You are right: concurrent gc only applies to gen2 collections, and that it
suspends managed threads for only part of the collection, as opposed to
non-concurrent which suspends them for the entire collection.

Maoni has an in-depth blog entry about concurrent gc:
http://blogs.msdn.com/maoni/archive/2004/09/25/234273.aspx

Also, Gen0 has a larger budget under concurrent gc than non-concurrent.

-Chris
 
Hi LP

| I do have one more question; how can I monitor *real time* when GC starts
| running and what thread. In general how one monitors what application is
| doing what threads are running, how much memory is consumed, etc.
| Do you use some kind of special tool?

You can use Performance Counters to determine the amount of memory
consumed, and the CLR Profiler to glean certain information about the GC
heap.

As for real time analysis, try the SOS extension to WinDBG.

-Chris
 
Chris,
inline ***

Thanks,
Willy.

No, the GC doesn't have a dedicated thread, sorry if I implied that.
*** You didn't imply that, I did, suposed I was wrong and the threads were
not suspended.
You are right: concurrent gc only applies to gen2 collections, and that it
suspends managed threads for only part of the collection, as opposed to
non-concurrent which suspends them for the entire collection.

Maoni has an in-depth blog entry about concurrent gc:
http://blogs.msdn.com/maoni/archive/2004/09/25/234273.aspx
*** One of my favorite readings just like your blog stuff.
Also, Gen0 has a larger budget under concurrent gc than non-concurrent.
*** That's right, it's a little unfortunate that you only can get this on MP
boxes though.
 
Back
Top