Analysis of GC key methods

Source: Internet
Author: User
Tags mscorlib

Section II. Analysis of GC key methods

1. Dispose () method

Dispose can be used to release all resources, including hosted and unmanaged resources.

Most of the unmanaged resources require manual release. We should publish a method to release the unmanaged resources. There are many ways to release the unmanaged resources, the dispose method for implementing the idispose interface is the best, which can be used by your class libraryProgramUsers can clearly explain how to release your resources, and use the using statement in C # To automatically call the dispose method when leaving the statement block.

Note that if the base class implements the idispose interface, its derived class must also implement its own idispose and call the dispose method in the base class in its dispose method. Only in this way can you ensure that when you release resources after using a derived class instance, the resources are released together with the unmanaged Resources in the base class.

Episode: difference between using and try + finally

It can be said that there is no difference between the two, because using is only editor-level optimization, it has the same role as try + Finally, the following is a section usingCodeIn the Il stage, it is also presented in try + finally:

C #:

Msil:

However, using automatically calls the dispose () method of the idispose interface when the Code leaves the using block.

Code
Public partial class _ default: system. Web. UI. Page
{
Protected void page_load (Object sender, eventargs E)
{
Using (Dataset DS = new dataset ())
{
}
}
}

Code
. Method family hidebysig instance void page_load (Object sender,
Class [mscorlib] system. eventargs e) cel managed
{
// Code size 29 (0x1d)
. Maxstack 2
. Locals Init ([0] class [system. Data] system. Data. dataset ds,
[1] bool CS $4 $0000)
Il_0000: NOP
Il_0001: newobj instance void [system. Data] system. Data. Dataset:. ctor ()
Il_0006: stloc.0
. Try
{
Il_0007: NOP
Il_0008: NOP
Il_0009: Leave. s il_001b
} // End. Try
Finally
{
Il_000b: ldloc.0
Il_000c: ldnull
Il_000d: CEQ
Il_000f: stloc.1
Il_0010: ldloc.1
Il_0011: brtrue. s il_001a
Il_0013: ldloc.0
Il_0014: callvirt instance void [mscorlib] system. idisposable: dispose ()
Il_0019: NOP
Il_001a: endfinally
} // End Handler
Il_001b: NOP
Il_001c: Ret
} // End of method _ default: page_load

2. gc. Collect () method

If we explicitly call the collect interface of the garbage collector in the program, the garbage collector runs immediately to complete the marking, compression, and clearing of memory objects, using GC. collect (I) can also specify the recycle generation. However, aicken does not approve of explicit calls from you:

(1. GC. collect () does not just recycle memory, as described in section 1. After memory is recycled, GC reorganizes the memory and modifies the object pointer to keep the idle memory continuously, the CLR allocates memory sequentially to improve the efficiency of new objects. Computation resources are greatly consumed by memory compression and sorting.

(2) Few people care about when GC will run in addition to memory shortage and idle resources. In fact, the GC Runtime is also controlled by a component called "policy engine", which will observe the GC collection frequency and efficiency. It adjusts the GC Operation Frequency Based on the GC recovery effect, that is, when a GC recovery has a very high effect, it increases the GC operation frequency, and vice versa.

So if a natural collection happens, there will be very few spam objects, and the program explicitly calls the collection, then naturally, GC, although small gains, however, the policy engine considers that it is not worthwhile to collect such garbage. It may reduce the number of GC times. In this way, the natural pace of the garbage collector's efforts will be disrupted.

At the same time, the efficiency and frequency of object type creation will also be captured by the "Policy engine" to change the generation quantity and capacity.

Therefore, the extra GC calls are expensive and may even reduce the efficiency. The displayed call GC. collect () is actually using "Time for Space". In programming, we recommend the design principle of "space for time", such as using various caches.

There are also exceptions. If you know the entire application and know when a large amount of garbage will be generated, you can also display the method called.

In summary, do not display the call to GC. Collect (), because the server CPU is much more expensive than the memory!

3. destructor (finalize ())

We know that GC is only responsible for releasing managed resources, and the unmanaged resource GC cannot be released. Non-hosted resources such as file operations and database connections are generated.

The Finalize method is used to release unmanaged resources. It is equivalent to a destructor in C #. When the C # compiler compiles constructor, the Destructor is implicitly compiled into the code corresponding to finalize (), and the base is executed in the Finally block. finalize ().

Only unmanaged resources can be released in the destructor, rather than being destructed in any managed resources, for the following reasons:

(1) You cannot predict the running time of the destructor. It is not executed in order. When the Destructor is executed, the managed resources you operate on may have been released.

(2) objects that contain finalize () can be deleted only after two GC operations.

(3) CLR will execute the finalize () method of all objects on a separate thread. Without a doubt, frequent finalize () will reduce the system performance.

Next, let's focus on the second (2). It takes two GC times to clear the finalize () object.

First, you need to know the two queues related to finalize: The Finalization queue and the reachable queue. These two queues store a group of pointers to objects.

When the program allocates space on the hosting stack (new), if this class contains destructor, GC will add a pointer to this object in Finalization queue.

When GC is run for the first time, it will traverse objects that have been confirmed as spam. If a pointer to a spam object is included in the Finalization queue, GC will separate the object from the spam, store its pointer to freachable queue and delete the pointer record of this object in Finalization queue, in this case, the object is not spam-this process is called the resurrection of the object ). Once a pointer is added to the freachable queue, it executes the finalize () method of the object to clear the resources occupied by the object.

When the GC runs again, it will find the garbage object containing the finalize () method again, but now it has no records in the Finalization queue (the Finalization queue record is deleted during the first GC runtime), then this object will be recycled.

At this point, through the GC two operations, the object with the Destructor is finally recycled.

Resurrection instance:

Code
Private void form1_load (Object sender, eventargs E)
{
Resource Re = new resource ();
Re = NULL; GC. Collect ();
GC. waitforpendingfinalizers ();
// The first GC. Collect () does not work.
Label1.text = Re. Num. tostring ();
}
Public class Resource
{
Public int num;
~ Resource ()
{
...
}
}

After reading the above Code, you should know what is resurrection! So why should we restore our lives? Because at the first GC, The finalize () method of this object has not been executed yet. If the finalize () method is not re-generated, the finalize () method is recycled together. Finalize () it cannot be run, so it must be re-generated to execute its finalize () and then recycled.

There are two other methods: reregisterforfinalize and suppressfinalize. reregisterforfinalize is to re-Add the pointer to the object to the Finalization queue (that is, call the system to execute the finalize () method ), suppressfinalize is to remove the object pointer from the Finalization queue (that is, deny the system to execute the finalize () method ).

Suppressfinalize is used to release resources by using the Destructor and the dispose () method. suppressfinalize (this) is added to the dispose () method to ensure that GC does not have to be collected again after the programmer calls dispose (). For example, the following code:

That is to say, the dispose () method in idisposable is implemented, and the Destructor is used. This method is double-insurance. Don't be confused. In fact, when releasing unmanaged resources, you can use one. We recommend that you use the former method.

Code
Public class Resource: idisposable
{
Private bool isdispose = false;
// Implement dispose (), followed by destructor to prevent the programmer from forgetting to call the dispose () method
Public void dispose ()
{
Dispose (true );
GC. suppressfinalize (this );
}
Protected virtual void dispose (bool disposing)
{
If (! Isdispose)
{
If (disposing)
{
// Clear managed resources
}
// Clear unmanaged Resources
}
Isdispose = true;
}
~ Resource ()
{
Dispose (false );
}
}

4. weakreference)

Last topic: weak references. In programming, we recommend that you use this reference method for large objects. This reference does not affect GC collection: We have used an object and then converted it to null, in this way, GC can be quickly recycled, but it will not be long before we need this object, so we have to re-create the instance, thus wasting the computing resources required to create the instance; if not null, memory resources will be wasted. In this case, we can create a weak reference for this large object, so that GC can be quickly recycled when the memory is not enough, and we can reuse this object again before being recycled by GC.

Code
Public class someobject
{
...
}
Public static void main ()
{
Someobject so = new someobject ();
Weakreference wrso = new weakreference (so );
So = NULL;
Console. writeline (wrso. isalive); // true
// Call GC for manual collection.
GC. Collect ();
Console. writeline (wrso. isalive); // false
}

No. After so = NULL, its weak reference is still available. Therefore, we recommend that you use aicken for large objects. In addition, weak references have different lengths: Long and weak references still track objects after the end of objects; short and weak references, on the contrary, aicken does not recommend manual intervention in GC results, therefore, we recommend that you use short and weak references, that is, the method in the code above.

Through the above explanation, we believe that you can fully understand the. net gc knowledge.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.