Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / CLR / April 2005

Tip: Looking for answers? Try searching our database.

How GC Works

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
saurabhgarg2k@gmail.com - 06 Apr 2005 11:04 GMT
Hi there,

I am attaching a snippet of code here which tries to explain that if u
have a class which contains both Unamanged resources and allocates a
lot of memeory and have a finalize method, then u should divides it
into two classes , one contains the memory part and other manages the
unmanaged resources and implement finalize in the second class so that
the memory will be released quick enough for first Class which
allocates large memory as classes implementing finalize method requires
at least 2 GC cycles to release the objects.

Here is the first class with contains both large memory and Unamaged
resources in one class

Class SimpleObject
   Private Declare Function CreateSemaphore _
      Lib "kernel32" Alias "CreateSemaphoreA" _
      (ByVal lpSemaphoreAttributes As Integer, _
      ByVal lInitialCount As Integer, _
      ByVal lMaximumCount As Integer, _
      ByVal lpName As String) As Integer
   Private Declare Function ReleaseSemaphore _
      Lib "kernel32" Alias "ReleaseSemaphore" _
      (ByVal hSemaphore As Integer, _
      ByVal lReleaseCount As Integer, ByVal _
      lpPreviousCount As Integer) As Integer

   Dim arr() As Integer
   Dim handle As Integer

   Sub New()
       ReDim arr(10000)    ' a lot of memory
       ' directly allocate an unmanaged resource
       handle = CreateSemaphore(0, 1, 1000, _
          "testsemaphore")
   End Sub

   Protected Overrides Sub Finalize()
       ' release the unmanaged resource
       If handle <> 0 Then _
          ReleaseSemaphore(handle, 1, 0)
   End Sub
End Class

Here is the Next Class which divides the functionality which is
embedded in the outer class.

Class CompoundObject
   Dim arr() As Integer
   Dim wrapper As SemaphoreWrapper

   Sub New()
       ReDim arr(10000)     ' a lot of memory
       ' allocate another (managed) resource
       ' (no need to release it in Finalize)
       wrapper = New SemaphoreWrapper
   End Sub

   ' a class that wraps the unmanaged resource
   Private Class SemaphoreWrapper

       Private Declare Function CreateSemaphore _
       Lib "kernel32" Alias "CreateSemaphoreA" _
          (ByVal lpSemaphoreAttributes As Integer, _
          ByVal lInitialCount As Integer, _
          ByVal lMaximumCount As Integer, _
          ByVal lpName As String) As Integer

       Private Declare Function ReleaseSemaphore _
       Lib "kernel32" Alias "ReleaseSemaphore" _
       (ByVal hSemaphore As Integer, _
       ByVal lReleaseCount As Integer, _
       ByVal lpPreviousCount As Integer) As Integer

           Public Handle As Integer
       Sub New()
           ' allocate the unmanaged resource
           Handle = CreateSemaphore(0, 1, 1000, _
              "testsemaphore")
       End Sub

       Protected Overrides Sub Finalize()
           ' release the unmanaged resource
           If Handle <> 0 Then _
              ReleaseSemaphore(Handle, 1, 0)
       End Sub

   End Class
End Class

Here is the Client Code

Module Module1
   Sub Main()
       Dim i As Integer
       Const TIMES As Integer = 10000

       Dim t As Date = Now
       For i = 1 To TIMES
           Dim so As New SimpleObject
       Next
       Console.WriteLine("Simple object: {0}", _
          Now.Subtract(t))

       ' force a garbage collection to clean up
       GC.Collect()
       GC.WaitForPendingFinalizers()

       t = Now
       For i = 1 To TIMES
           Dim co As New CompoundObject
       Next
       Console.WriteLine("Compound object: {0}", _
          Now.Subtract(t))
       Console.ReadLine
   End Sub
End Module

Now the author claims that the first for loop will take more time as it
requires more GC cycles to deallocate the large chunk of memory it
allocates and the second will release it quickly as the class
allocating the Large memory does not implement finalize method so it
will be deallocated in one GC cycle unlike the class with unmamaged
resource.

My question:
As GC will only fire when managed heap runs out of space, so in first
for loop when after allocating a few objects, heap is full and the GC
fires but no objects will be allocated as the class implements the
Finalize method and it requires at least two GC cycles to deallocate,
so if no object is deallocated, from where the runtime gets the space
to allocate the next object,will GC be fired again for these kind of
cases when it does not able to release enough memory for the next
object or what.

Note:
The code works fine.No Exceptions so there is something missing in my
understanding.

Excuse me for such a long posting but i would highly appreciate if
someone clears my doubt where i am wrong.

Thanks and Regards
Saurabh Garg
"Chris Lyon [MSFT]" - 07 Apr 2005 19:27 GMT
Hi Saurabh

A couple of points:

-There are several situations that will trigger the GC to peform a
collection, most of which occur before the entire heap is full.  Maoni has
some great explanations at http://blogs.msdn.com/maoni/

-If your class uses unmanaged resources, it shoud use the Dispose Pattern,
and not rely on finalization.  This will solve the problem of your object
being promoted a generation due to being put on the finalization queue.
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/h
tml/cpconfinalizedispose.asp)

More information about finalization, GC and Performance:
http://blogs.msdn.com/ricom/
http://blogs.msdn.com/cbrumme
http://blogs.msdn.com/clyon

Hope that helps
-Chris

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

| Hi there,
|
[quoted text clipped - 140 lines]
| Thanks and Regards
| Saurabh Garg
saurabhgarg2k@gmail.com - 08 Apr 2005 15:09 GMT
Hi Lyon,

Thanks for the Reply, but actually there is no problem with the Code,
actually its a sample code,what i was trying to understand that the
author of the code is saying that First For Loop works slower than
second and it does, i was just trying to understand how.His Explanation
is:

In the First For loop,there is only one class which implements Finalize
method and since the Class With finalize method requires at least two
GC Cycles to clean up the memory, so result is that the huge amount of
memory it allocates will not get cleared up in one GC Cycle and so
managed heap will be full again soon which makes GC runs too frequently
and makes application slower.

But in the second for loop he seperates the Class in two Classes, one
with Finalize and the other with huge memory, so his point is that now
the Class which allocates huge memory does not implement Finalize
method and will get cleared up in one GC cycle and dellocates the huge
memory which in turn results in less GC runs and application runs
faster.

Now wat my doubt is:
As we know that GC will happen after managed heap is full (but as u
said it might not be the case), but lets say it does,so in the first
case no objects will be deallocated because all objects in the heap are
of the type which implements Finalize method, and they need at least
two GC cycles, so if no memory is freed, where from the CLR gets the
space to give it to the new object.Will GC run again and again unless
the memory gets sufficiently cleared for the new object.

Looking forward for a reply

Thanks and Regards
Saurabh Garg

> Hi Saurabh
>
[quoted text clipped - 7 lines]
> and not rely on finalization.  This will solve the problem of your object
> being promoted a generation due to being put on the finalization queue.

(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/h
> tml/cpconfinalizedispose.asp)
>
[quoted text clipped - 152 lines]
> | Thanks and Regards
> | Saurabh Garg
"Chris Lyon [MSFT]" - 08 Apr 2005 18:23 GMT
| Now wat my doubt is:
| As we know that GC will happen after managed heap is full (but as u
[quoted text clipped - 4 lines]
| space to give it to the new object.Will GC run again and again unless
| the memory gets sufficiently cleared for the new object.

If the heap is completely full, and you try to allocate a new object, the
GC will attempt to collect the heap, generation by generation.  After it
has collected all generations and the Large Obect Heap, the finalizer
thread will run the Finalize methods for all objects on the finalizer queue
(so objects that implement finalizers are in fact kept alive for more GC
collections).

If after all this, there is still no heap available to allocate a new
object, an OutOfMemoryException will be thrown.

(this is obviously a simplified explanation of what happens, see the links
I posted yesterday for more in-depth info).

Hope that helps
-Chris
Richard Blewett [DevelopMentor] - 14 Apr 2005 02:11 GMT
Chris,

Why don't you perform another full GC after the finalizers have run as you can now most likely collect these objects (resurrection apart)? This may free up enough memory preventing the necessity of throwing the OutOfMemoryException.

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

  If the heap is completely full, and you try to allocate a new object, the
GC will attempt to collect the heap, generation by generation. After it
has collected all generations and the Large Obect Heap, the finalizer
thread will run the Finalize methods for all objects on the finalizer queue
(so objects that implement finalizers are in fact kept alive for more GC
collections).

If after all this, there is still no heap available to allocate a new
object, an OutOfMemoryException will be thrown.

Ravichandran J.V. - 14 Apr 2005 10:28 GMT
It is a long post so I will try to clear your basic questions first. One, GC
is not only fired when there is no heap space in memory but also when Gen 0
is full or nearly full.  Gen 0 is the critical area which worries the GC and
hence, whenever this Gen is full or when a new object is created, GC will be
invoked automatically.

Two, if an object implements a Finalize method, the GC will be forced to run
the Finalizer for the object before disposing it and hence, it will take
longer for new objects to be created if memory is critical. Because as soon
as a new object is created, that object will be allocated memory on Gen 0,
all older objects will be promoted from Gen 0 to 1 and from 1 to 2 and 2 will
keep expanding until there is no more memory in the system. So, as a new
object allocation is requested GC will automatically create space for it, if
memory exists in the system, in Gen 0.

with regards,

J.V.

> Hi there,
>
[quoted text clipped - 140 lines]
> Thanks and Regards
> Saurabh Garg

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.