.net CLR 4.0废品回收机制的改革之3

A survey of garbage collection and the changes CLR 4.0 brings in Part 3

  • series of what is new in CLR 4.0
    接前篇Continue the previous posts

 .net CLR
4.0对污染源回收机制的革新

.net CLR
4.0对垃圾回收机制的改正2

 

弱引用Weak Reference

mm小游戏

弱引用是争持强引用来说的。强引用指的是根有一个指针指向对象。弱引用是由此对强引用加以弱化而取得的。这个弱化的手段就是用System.WeakReference类。所以精确地说,强引用指的是根有一个非WeakReference类型的指针指向对象,而弱引用就是根有一个WeakReference类型的指针指向对象。垃圾收集器看到一个WeakReference类型的根指向某个对象,就会特意处理。所以在废品收集器成立对象引用关系图的时候,假诺赶上一个弱引用指针,那么垃圾收集器就不会将其投入图中。倘诺一个目的唯有弱引用指向它,那么垃圾收集器能够收集此目的。一旦将一个强引用加到对象上,不管对象有没有弱引用,对象都不可回收。

 

Weak reference is corresponding to strong reference. Strong reference is
that a root is pointing to an object. Weaken a strong reference and get
a weak reference. The facility to weaken strong reference is the
System.WeakReference class.  An exact definition is that, strong
reference is that a root has a non-System.WeakReference type pointer
pointing to an object, and weak reference is that a root has a
System.WeakReference type pointer pointing to an object. Garbage
collector treats the roots of WeakReference type in a special way.
Therefore, when garbage collector is building the reference relationship
graph, if there is a weak reference pointer, and then garbage collector
will not append it to the graph. If an object only has weak references
pointing to it, garbage collector can collect the object. Once a strong
reference is pointing to the object, no matter whether the object has
weak references or not, the object can not be collected.

废品收集器对WeakReference类的特别处理从new操作就从头。常常的类,只要new操作,就会从托管堆分配空间,而WeakReference类的new操作不是这般做的。大家先来看WeakReference类的构造函数:

The special treatment that garbage collector deals with WeakReference
class starts from the new operation. A common class will allocate space
from managed heap when new operation, but CLR does not do like that for
WeakReference class when new operation. Let’s look at the constructors
of WeakReference class:

WeakReference(Object target);

美人小游戏

WeakReference(Object target, Boolean trackResurrection);

此二构造函数都需要一个对象的引用,第二个构造函数还索要一个布尔值参数来代表我们是否需要跟踪对象的重生。此参数的含义后文会交代。

The two constructors both need a reference of an object, and the second
constructor needs one more, a parameter of boolean type to indicate
whether we need to track the resurrection of the object. The exact
meaning of the parameter will be talked about later.

假使我们有三个类MyClass和MyAnotherClass,都有Finalize方法。我们注明七个对象:

Suppose we have two classesMyClass and MyAnotherClass, and both of
classes have Finalize method.

MyClass myObject = new MyClass();

MyAnotherClass myAnotherObject = new MyAnotherClass();

当我们用如此的代码阐明一个弱引用对象: WeakReference
myShortWeakReferenceObject = new WeakReference( myObject );

When we use such a snippet of code to declare a weak reference object:
WeakReference myShortWeakReferenceObject = new WeakReference( myObject
);

垃圾收集器内部有一个短弱引用表,用如此阐明的弱引用对象将不会在托管堆中分配空间,而是在短弱引用表中分配一个槽。此槽中记录对myObject的引用。New操作将此槽的地点重临给myShortWeakReferenceObject变量。

Garbage collector has a short weak reference table inside, the weak
reference object declared in such a way will not allocate space from
managed heap, and a slot will be allocated in the short weak reference
table for the weak reference object. The slot records the referene of
myObject. New operation returns the address of the slot to
myShortWeakReferenceObject variable.

假如大家用这样的代码阐明一个弱引用对象(大家要盯住该目的的重生):
WeakReference myLongWeakReferenceObject = new WeakReference(
myAnotherObject, true );

When we use such a snippet of code to declare a weak reference object(We
need to track resurrection of the object): WeakReference
myLongWeakReferenceObject = new WeakReference( myAnotherObject, true );

垃圾收集器内部有一个长弱引用表,用这样注明的弱引用对象将不会在托管堆中分配空间,而是在长弱引用表中分红一个槽。此槽中记录对myAnotherObject的引用。New操作将此槽的地方重回给myLongWeakReferenceObject变量。

Garbage collector has a long weak reference table inside, the weak
reference object declared in such a way will not allocate space from
managed heap, and a slot will be allocated in the long weak reference
table for the weak reference object. The slot records the referene of
myAnotherObject. New operation returns the address of the slot to
myLongWeakReferenceObject variable.

废品收集器此时的采集流程是这样的: The collecting process of garbage
collector in this scenario is looking like the follwoing:

1.
废品收集器建立目标引用图,来找到所有的可到达目的。前文已经说过怎么树立图。特其余地点是,假如赶上非WeakReference指针,就投入图,假使遭逢WeakReference指针,就不参与图。这样图就建好了。Garbage
collector builds up the reference ralationship graph to find all the
reachable objects. The way to build up the graph is mentioned earlier.
The special space is, if encounters a non-WeakReference pointer, then
appends it to the graph, if meets a WeakReference pointer, then does not
append it to the graph. The graph is built in this way.

2.
破烂收集器扫描短弱引用表。即使一个指南针指向一个不在图中的对象,那么此目的就是一个不可到达的靶子,垃圾收集器就将短弱引用表相应的槽置空。Garbage
collector scans the short weak reference table. If a pointer pointing to
an object not in the graph, then the object is not a reachable object,
and then garbage collector sets the slot to null in the short weak
reference table.

3.
破烂收集器扫描停止队列。如果队列中一个指南针指向一个不在图中的对象,此指针将被从截止队列移到待截至队列,同时此目的被投入引用关系图中,因为此时此对象是Finalize可抵达的。Garbage
collector scans the Finalization queue. If a pointer in the queue
pointing to an ojbect not in the graph, then the pointer will be moved
to the ToBeFinalized queue, and the object will be appended to the
reference relationship graph, because the object is Finalize reachable
at this time.

4.
垃圾收集器扫描长弱引用表。假设一个指南针指向一个不在图中的对象(注意此时图中已盈盈Finalize可到达的目标),那么此目的就是一个不足到达的靶子,垃圾收集器就将长弱引用表相应的槽置空。Garbage
collector scans the long weak reference table. If a pointer pointing to
an object not in the graph, then the object is not a reachable object,
and then garbage collector sets the slot to null in the long weak
reference table.

  1. 垃圾堆收集器夯实(压缩)托管堆。 Garbage collector tamps(or compacts) the
    managed heap.
    短弱引用不跟踪重生。即垃圾收集器发现一个对象为不可到达就当下将短弱引用表相应的槽置空。假设该对象有Finalize方法,并且Finalize方法还不曾实施,所以该目的就还设有。假诺应用程序访问弱引用对象的Target属性,固然该目标还留存,也会获取null。

Short weak reference does not track resurrection. It means that garbage
collector sets the slot to null in the short weak reference table as
soon as finds an object not reachable. If the object has a Finalize
method, and its Finalize method has not been executed, then the object
still exists. If the applicaiton accesses the Target property of the
weak referene object, and gets null even though the object still exists.

长弱引用跟踪重生。即垃圾收集器发现一个对象是Finalize可抵达的目的,就不将相应的槽置空。因为Finalize方法还尚未进行,所以该对象就还存在。假若应用程序访问弱引用对象的Target属性,可以收获该对象;不过只要Finalize方法已经被实践,就标志该对象没有重生。

Long weak reference tracks resurrection. It means that garbage collector
does not set the slot to null in the long weak reference table when
garbage collector  meets an object is Finalize reachable. Because the
Finalize method has not been executed, the object still exists. If the
application accesses the Target property of the weak reference object,
and gets the object. But if the Finalize method has been executed, then
the object is not resurrected.

按照地方的事例,如若执行如下代码会时有发生怎么样吗?Continue the above
example, what will happen if we execute the following code?

//File: MyClass.cs
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication2

丽人小游戏打分装扮小游戏
古装公主小游戏
装扮仙女小游戏
化妆男友小游戏
婚纱礼服小游戏
光洋妹小游戏
Barbie娃娃小游戏
布置房间小游戏
照顾小婴孩小游戏
思维测试小游戏
连连看
对对碰
找不同
泡泡堂
祖玛
一流玛丽(Mary)
黄金矿工

{
    class MyClass
    {
        ~MyClass()
        {
            Console.WriteLine(“In MyClass
destructor+++++++++++++++++++++++++++”);
        }
    }
}//File: MyAnotherClass.cs
using System;
using System.Collections.Generic;
using System.Text;

 

namespace ConsoleApplication2
{
    public class MyAnotherClass
    {
        ~MyAnotherClass()
        {
            Console.WriteLine(“In MyAnotherClass
destructor___________________________________”);
        }
    }
}//File: Program.cs
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass myClass = new MyClass();
            MyAnotherClass myAnotherClass = new MyAnotherClass();
            WeakReference myShortWeakReferenceObject = new
WeakReference(myClass);
            WeakReference myLongWeakReferenceObject = new
WeakReference(myAnotherClass, true);
            Console.WriteLine(“Release managed resources by setting
locals to null.”);
            myClass = null;
            myAnotherClass = null;

            Console.WriteLine(“Check whether the objects are still
alive.”);
            CheckStatus(myShortWeakReferenceObject, “myClass “,
“myShortWeakReferenceObject”);
            CheckStatus(myLongWeakReferenceObject, “myAnotherClass”,
“myLongWeakReferenceObject”);

            Console.WriteLine(“Programmatically cause GC.”);
            GC.Collect();

            Console.WriteLine(“Wait for GC runs the finalization
methods.”);
            GC.WaitForPendingFinalizers();

            //Check whether the objects are still alive.
            CheckStatus(myShortWeakReferenceObject, “myClass “,
“myShortWeakReferenceObject”);
            CheckStatus(myLongWeakReferenceObject, “myAnotherClass”,
“myLongWeakReferenceObject”);

            Console.WriteLine(“Programmatically cause GC again. Let’s
see what will happen this time.”);
            GC.Collect();

            //Check whether the objects are still alive.
            CheckStatus(myShortWeakReferenceObject, “myClass “,
“myShortWeakReferenceObject”);
            CheckStatus(myLongWeakReferenceObject, “myAnotherClass”,
“myLongWeakReferenceObject”);

            myAnotherClass =
(MyAnotherClass)myLongWeakReferenceObject.Target;

            Console.ReadLine();
        }

        static void CheckStatus(WeakReference weakObject, string
strLocalVariableName, string strWeakObjectName)
        {
            Console.WriteLine(strLocalVariableName + (weakObject.IsAlive
? ” is still alive.” : ” is not alive.”));
            Console.WriteLine(strWeakObjectName + (weakObject.Target !=
null ? “.Target is not null.” : “.Target is null.”));
            Console.WriteLine();
        }
    }
}
请大家想一想倘使MyAnotherClass类没有Finalize方法吧? Please think about
what if the MyAnotherClass class does not have Finalize method.

或者:如若我们诠释掉这行: GC.WaitForPendingFinalizers();,
试着多执行此代码多次,
看看每便会输出什么啊?是不是Finzalization方法被执行的机遇不确定? Or, if
we comment the line: GC.WaitForPendingFinalizers();, and try to execute
the code multiple times, let’s see what will be the outputs. Is it that
the time to execute Finalization methods is uncertain?

弱引用是为大目标准备的。在实际上当中,假如不用弱引用,只用强引用,则用过了该大对象,然后将强引用置null,让GC可以回收它,不过没过多长时间大家又需要以此大目的了,但是曾经没有章程找回原来的目标,只能重新创立实例,那样就浪费了制造实例所需的乘除资源;而假若不置null,就会占据很多内存资源。对于这种景色,我们得以创设一个以此大目的的弱引用,这样在内存不够时将强引用置null,让GC可以回收,而在一向不被GC回收前,假若我们长期内还亟需该大对象,我们还足以另行找回该目标,不用再重复创制实例。是不是节约了一部分开销?

Weak reference is for large objects. In our daily practice, if we do not
use weak reference, only use strong reference, it happens that we use a
largae object and set it to null and let GC collect it, and we need the
large object soon later, but there is no way find the original object
back, we have to instanciate a new large object. That way we are wasting
computer resources to create the old instance, but if we do not set the
object to null, it occupies lot of memory. In this case, we can create a
weak reference of the large object, and set strong reference object to
null when there is not enough memory and let GC collect the large
object, and we can find the large object back when we have requirement
before the large object has not been collected by GC. No need to create
a new instance, does this way save costs?

废品收集的相似流程The common process of garbage collection
以下是污染源收集的相似流程,受应用场景(如服务器应用,并发和非并发)影响,具体的污物回收流程可能截然不同。The
following is the common process of garbage collection, because of
different scenarios and factors(like server application scenario,
concurrent or non-concurrent), the actual processes are a little
different.

  1. 挂起.net应用的所无线程Suspend all the threads of .net application

  2. 找到可回收的靶子Find all the reclaimable objects

  3. 回收可回收的目的并缩减托管堆Reclaim the reclaimable objects and
    compact the managed heap

  4. 接轨.net应用的所无线程Resume all the threads of .net application

垃圾收集的格局The modes of Garbage collection
CLR4.0在此以前,一共有二种情势的GC,分别针对不同品类的应用程序而优化:Server版非并发GC,
Workstation版并发GC, 和Workstation版非并发GC. Before CLR 4.0, there are
three different modes of GC, which are optimized for different types of
applications: Server version Non–concurrent GC, Workstation version
concurrent GC, and Workstation version Non-concurrent GC.

Server GC – Non Concurrent
Server
GC是指向服务器应用而举行优化的,目标是为了保证其高吞吐量和高的规模可扩展性。The
server non-concurrent GC is optimized for high throughput and high
scalability in server applications.

Server GC
为每一个总计机分配一个托管堆和一个GC线程。各GC线程独立工作在分级的堆上,那样最大程度地裁减了锁,从而确保了此种境况下的迅速。这个GC线程是非并发的(第0代,第1代,第2代都是非并发的,即在征集时都要截止所有应用程序的线程,直到采访停止)。同时这多少个GC线程是特地的线程,不同于应用程序的线程。The
server GC allocates one heap and one GC thread for each of processors.
The GC threads work on their respective heaps,  and this minimizes the
possibilities to lock resources, and ensures high efficiency in the
server situation. The GC threads are non-concurrent(Gen 0, Gen 1 and Gen
2 are non concurrent, meaning that garbage collector suspends all the
threads of application at collecting cycles of generations until the
collecting finishes). Meanwhile the GC threads are dedicated threads,
different from the threads of application.

实在的Server GC工作流程是这般的:The actual work flow of server GC is
looking like the following:

  1. 应用程序的线程在其托管堆上分配空间The application threads are doing
    allocations on their corresponding managed heap;

  2. 其托管堆没有更多空间来分配托管对象They run out of allocations on the
    heaps their allocating on;

  3. 于是乎触发一个轩然大波,让GC线程来做采访,并听候GC线程完成采访That signals
    an event to wake the GC threads to do a GC and waits for it to finish;

4.
GC线程运行,完成采访并爆发完成事件(在GC线程运行期间,应用程序线程是暂停的)GC
threads run, finish with the GC and signal an event that says GC is
complete (When GC is in progress, all the application threads are
suspended);

  1. 应用程序的线程继续运行The application threads resume running.

这连串型的GC唯有在多处理器的机器上可见,假使您在单处理器上的安装这种模式,这你将获取workstation版本非并发的GC。The
Server Non-concurrent GC is only available on multi processor machines.
If you try to set the server GC on a machine with single processor you
will instead get the workstation version with non concurrent GC.

Asp.net的使用在多cpu的机器上默认使用这种形式,还有其余一些品类的服务器应用也在多cpu的机器上采纳这种情势。例如如若您想在Windows服务上应用server
GC情势,你可以在应用程序配置文件中做如下设置:ASP.NET applications use
the mode by default on multiproc machines, as well as a number of other
types of server applications. For example, if you want to use the server
GC in a windows service you can do so by setting in the application’s
config file:

<configuration>
<runtime>
   <gcServer enabled=”true” />
</runtime>
</configuration>

Workstation GC – Concurrent
Winform应用程序和Windows services 服务程序默认使用这种情势。This is the
default setting for win forms applications and windows services.

这种情势是本着交互式应用程序优化的,这种程序要求应用程序不能够暂停,尽管是一个对峙很短暂的时辰也是至极的。因为暂停进程会让用户界面闪烁或者当点击按钮的时候感觉应用程序没有响应。The
Workstation GC is optimized for interactive applications that can’t
allow for the application to be paused even for relatively short periods
since pausing the threads would cause flicker in the user interface or
make the application feel non responsive to button clicks etc.

在这种情势下,第0代和第1代的搜集依然是要中断应用程序的线程直到采访完毕,因为第0代和第1代的募集速度神速,所以并未必要去做并行。所谓的面世是在需要第2代收集时,大家可以选拔让第2代收集并行地推行或者暂停应用程序的所无线程直到采访停止。即使我们尚无做取舍,那么默认的就是第2代收集是相互的。In
this mode, the collection of gen 0 and gen 1 still need to pause all the
threads of application until the collection of gen 0 and gen 1 finishe.
Since the gen 0 and gen 1 collections are very fast, it does not make
sense to have concurrent GC when we do gen 0 and gen 1 collections. The
concurrent is that we can choose whether we do concurrent collection
when it is gen 2 collection or suspend all the threads of application
until the collection finish. If we do not make the choice, then the
default is that the gen 2 collection is concurrent.

有一个专门的GC线程来并行地收集排泄物。在第2代收集时,用更多CPU周期和堆内存来换取更短的用户界面停立即间。There
is a dedicated GC thread collecting garbage in parallel mode. This is
done by trading a little bit more CPU cycles and heap memory usage for
shorter UI pause time when doing gen 2 collections.

交互收集依旧需要在搜集过程中间断应用程序多次,但这四回暂停相对较短,对UI线程影响较小。应用程序线程在相互收集举办中可以同时分配对象。这就要求第0代有较大的半空中和较高的触发Gen
0收集的阀值。假如应用程序用完第0代的内存,而互相收集还并未进展扫尾,那么应用程序不得不中断下来,等待并行收集的做到。Concurrent
collection still needs to suspend the application multiple times during
the concurrent collecting cycle. , but the the times of pause are
shorter than usual, have less impact on the UI thread. The application
can allocate objects while the concurrent collection is going on. This
requires that the gen 0 has bigger space and higher threshold to trigger
collection on gen 0. If the application exhausts the memory of gen 0,
and the concurrent collection is not finished, then the application has
to suspend to wait for the concurrent collection finishes.

就算我们要做采纳,让应用程序在交互形式下运作,可以在应用程序的config文件中写上:
If we make the choice to let the application run under concurrent mode,
please leave this in the config file of the application.

<configuration>

<runtime>

<gcServer enabled=“true”/>

</runtime>

</configuration>

注: Jeffrey Richter似乎在其书<<CLR via c#>>中说concurrent
GC只有在多CPU机器上有。然则通过马克的检察,实际上concurrent
GC在单CPU上也有。

Note: Jeffrey Richter seemed to mention in his book <<CLR via
c#>> that concurrent GC is only available on multiple CPUs
machine, but according to Mark’s investigation, concurrent GC is also
available on single CPU machine.

Workstation GC – Non Concurrent
这种形式与Server
GC类似,推荐为这种运行在单个cpu机器上服务类型的应用程序使用。与Server
GC不同的是:其募集线程即一律应用程序线程。那是这种情势的劳作流程:The
mode is similar to the Server GC mode, and is recommended for the server
applications running on single processor machine. The collection happens
on the same threads of application, which is different from what the
Server GC does. The following is the work flow of the mode:

1) 应用程序线程在堆上分配对象Application threads are doing allocations
on the heap;

2) 第0代没有充裕空间It runs out space in gen 0.

3) 在同一线程上吸引垃圾收集It triggers a GC which will be running on
this very thread;

4) 垃圾收集器调用SuspendEE函数暂停使用程序线程GC calls SuspendEE to
suspend the application’s threads;

5) GC做采访工作GC does its work;

6) GC调用RestartEE来继续应用程序的线程GC calls RestartEE to restart the
application’s threads;

7) 应用程序的线程继续运行Application threads start running again.

可以修改应用程序的部署来把 concurrency 关闭。We could close concurrency
using the following setting in the application’s config file.

 <configuration>
<runtime>
   <gcConcurrent enabled=”false” />
</runtime>
</configuration>

下面是三种情势的对待表This is the comparison matrix of the modes:

  Concurrent WS
 Non-Concurrent WS
 Server GC
 
Design Goal
 Balance throughput and responsiveness for client apps with UI
 Maximize throughput on single-proc machines
 Maximize throughput on MP machines for server apps that create multiple
threads to handle the same types of requests
 
Number of heaps
 1
 1
 1 per processor (HT aware)
 
GC threads
 The thread which performs the allocation that triggers the GC
 The thread which performs the allocation that triggers the GC
 1 dedicated GC thread per processor
 
Execution Engine Suspension
 EE is suspended much shorter but several times during a GC
 EE is suspended during a GC
 EE is suspended during a GC
 
Config setting
 <gcConcurrent enabled=”true”>
 <gcConcurrent enabled=”false”>
 <gcServer enabled=”true”>
 
On a single processor machine
     WS GC + non-concurrent
 
 

上述大家说到了CLR 4.0往日垃圾收集的大多数上面。
精晓前边的知识有助于精晓CLR 4.0所带来的成形。We introduced most of
aspects of garbage collection prior to CLR 4.0. Master the legacy to
help undetstand the changes CLR 4.0 brings in.

CLR 2.0将来GC有哪些变化呢?What are the changes since CLR 2.0?
CLR V4.0拉动的后台垃圾收集The background GC brought to you by CLR 4.0
眼前大家早已涉嫌曾经有了产出垃圾收集。后台垃圾收集是来代替并发垃圾收集。后台垃圾收集是出新垃圾收集的开拓进取。We
mentioned there has been concurrent GC. Background GC is to replace
concurrent GC. Background GC is an evolution to concurrent GC.

当应用程序的活动量不大(包括分配和改动引用)并且堆不太大时,并发垃圾收集工作得好。由并发垃圾收集带来的延期是可接受的。不过当众人编写更大的应用程序,需要利用更大的堆,那时由并发收集带来的延迟就变得不行接受。When
the program activity (including making allocations and modifying
references) is not really high and the heap is not very large concurrent
GC works well – the latency caused by the GC is reasonable. But as
people start writing larger applications with larger heaps that handle
more stressful situations, the latency can be unacceptable.

后台垃圾收集的明显立异是:在后台垃圾收集举办中,假如需要的话,大家可以做短的废品收集(第0代和第1代收集)。与出新垃圾收集类似,后台垃圾收集也是唯有在方方面面垃圾堆收集时才有。并且短的污物收集(第0代和第1代收集)总是按阻断形式开展垃圾收集(暂停应用程序)。后台垃圾收集在一个特意的线程上运行。那几个与后台垃圾收集同时举行的短垃圾收集(第0代和第1代收集)被称为前台垃圾收集。

The significance of background GC is we can do ephemeral GCs(gen 0 and
gen 1 GC) while a background GC is in progress if needed. As with
concurrent GC, background GC is also only applicable to full GCs and
ephemeral GCs are always done as blocking GCs(suspend the application),
and a background GC is also done on its dediated GC thread. The
ephemeral GCs(gen 0 and gen 1 GC) done while a background GC is in
progress are called foreground GCs.

于是乎,当后台垃圾收集正展开中而第0代空间不足,就会接触一个第0代垃圾收集(有可能升级成第1代收集,取决于垃圾收集器的里边决策)。后台垃圾收集线程会平时检查安全点(比如前台垃圾收集发出)。当有前台垃圾收集时,后台垃圾收集会自己暂停并让前台垃圾收集可以先河开头工作。在前台垃圾收集完成之后,后台垃圾时线程和应用程序的线程就延续它们的行事。

So when a background GC is in progress and you’ve allocated enough in
gen0, we will trigger a gen0 GC (which may stay as a gen0 GC or get
elevated as a gen1 GC depending on GC’s internal tuning). The background
GC thread will check at frequent safe points (ie, when we can allow a
foreground GC to happen) and see if there’s a request for a foreground
GC. If so it will suspend itself and a foreground GC can happen. After
this foreground GC is finished, the background GC thread and the user
threads can resume their work.

后台垃圾收集不仅在较低的代将无济于事的靶子清除,同时它提高了目的停留在短生命周期段的限量–假若后台垃圾收集举办中需要扩展堆,大家得以在第1代收集时这样做。而这在CLR1.0和CLR2.0只有在第2代收集时才会时有暴发。

Not only does this allow us to get rid of dead objects in young
generations, it also lifts the restriction of having to stay in the
ephemeral segment – if we need to expand the heap while a background GC
is going on, we can do so in a gen1 GC. In CLR1.0 and CLR 2.0, this only
happens when gen 2 GC .

后台垃圾收集比并发收集的功利体现在:在后台采访举行中,应用程序耗尽了第0代的半空中,假使是现身收集,应用程序必须暂停以等待并发收集完成。而明日不可同日而语了,可以用前台收集对第0代或者第1代举办募集。于是就无需等待。同时,假如需要,可以在第1代收集就扩展堆(增添内存段),而不必等到第2代收集。那裁减了让UI应用程序暂停的机遇。Advantages
of Background GC(versa to concurrent GC) are : During background GC, the
application runs out memory in gen 0, if it is concurrent GC, the
application has to suspend and wait for the finish of concurrent GC. But
now it is different, we can use forground GC to do collection on gen 0
or gen 1. therefore no need to wait for the finish of concurrent GC. And
meanwhile, we can expand the heap(by adding new memory segment) at gen 1
if required, do not have to wait until gen 2 GC. These minimize the
possibilities to suspend the UI application.

咱们经过互动地做更多工作革新了后台垃圾收集的特性,所以需要暂停应用程序线程的年华更短。我们前天一贯不在CLRV4.0中为Server
GC提供后台垃圾收集。这将是延续的行事。We also made some performance
improvement in background GC which does better at doing more things
concurrently so the time we need to suspend managed threads is also
shorter. We are not offering background GC for server GC in V4.0. That
is coming work.

.net 3.5 SP1中的全体采集通报机制Full GC notification in .net 3.5 SP1
任何募集通报机制是为负责大量伸手的服务器应用准备的。因为存在部分动静,CLR的全部收集会带来较大的延迟,从而影响服务器应用的特性,导致用户请求超时。针对这种状态,整体征集通报机制应运而生。当一个全垃圾收集将要起先时,你会获取关照并得以行使相应动作,如将请求导向其余服务器。

.net 3.5 SP1的GC类扩充了多少个措施:

GC.RegisterForFullGCNotification

GC.WaitForFullGCApproach

GC.WaitForFullGCComplete

GC.CancelFullGCNotification

并在System命名空间下扩展了一个枚举

GCNotificationStatus

本条GC.RegisterForFullGCNotification
用来注册当前使用将要接收全体废物收集的关照。当一个全方位废品收集将要发生时,注册了的应用程序就可接收通告。同时,当一个方方面面杂质收集完成时,注册了的程序也会收到通告。这是GC.RegisterForFullGCNotification
的阐发格局:

[PermissionSetAttribute(SecurityAction.LinkDemand, Name =
“FullTrust”)]
public static void RegisterForFullGCNotification(
    int maxGenerationThreshold,
    int largeObjectHeapThreshold
)maxGenerationThreshold是1-99中间的数.指的是第2代中现有的靶子个数达到这些阀值就要通知.
largeObjectHeapThreshold也是1-99里边的数.指的是大目的堆中分配的目标个数达到这么些阀值就要布告.

WaitForFullGCApproach用来收获垃圾收集器是否快要举办全方位垃圾堆收集.
它的表明是那样的:

[PermissionSetAttribute(SecurityAction.LinkDemand, Name =
“FullTrust”)]
public static GCNotificationStatus
WaitForFullGCApproach()或者[PermissionSetAttribute(SecurityAction.LinkDemand,
Name = “FullTrust”)]
public static GCNotificationStatus WaitForFullGCApproach(
    int millisecondsTimeout
)第2个调用模式可以带一个等候时间, 单位是纳秒.
其归来的是枚举GCNotificationStatus,
假虽然GCNotificationStatus.Succeeded,
那么大家就能够将请求导向其他服务器.与WaitForFullGCApproach类似的,
WaitForFullGCComplete用来得到垃圾收集器是否已经形成全部废物收集,
它的阐明是这么的:

[PermissionSetAttribute(SecurityAction.LinkDemand, Name =
“FullTrust”)]
public static GCNotificationStatus WaitForFullGCComplete()或者

[PermissionSetAttribute(SecurityAction.LinkDemand, Name =
“FullTrust”)]
public static GCNotificationStatus WaitForFullGCComplete(
    int millisecondsTimeout
)第2个调用格局得以带一个守候时间, 单位是毫秒.
其回来的是枚举GCNotificationStatus,
假使是GCNotificationStatus.Succeeded,
那么我们就足以将此服务器重新讲明可以接受外界的请求.

WaitForFullGCApproach和WaitForFullGCComplete设计时就是要一起使用的。假若只利用一个而不行使另一个就会导致不可知的结果。

GC.CancelFullGCNotification是用来将曾经注册的污染源收集通报撤废.
与GC.RegisterForFullGCNotification 一起成对配合使用.

一般说来的利用办法是如此的:

1.首先在主线程调用GC.RegisterForFullGCNotification 来准备收获通告

2.启动一个值守线程,
在值守线程中调用WaitForFullGCApproach和WaitForFullGCComplete来收获当前GC状态,
淌假诺即将举行任何破烂收集,就做相应处理,如将请求导向其他服务器。如如果一切垃圾收集完毕,则可做相应处理,
如将此服务器标记为可承受请求.值守线程中需要不断循环来轮循GC状态.

3.当主线程将要停止, 调用GC.CancelFullGCNotification并发音信文告值守线程,
值守线程退出循环,截止.

4.主线程退出

对于asp.net应用,
可以在Application_Start中调用GC.RegisterForFullGCNotification并启动一个值守线程.
同时可以在Application_End中通报值守线程停止.

整个污染源收集通报机制的独立用途就是在多服务器的场景.用NLB(Network load
balance)搭建的Web Farm或者硬件load balance的多服务器场景.
一个相比较复杂的面貌是各个服务器上还有web garden设置.

注意事项: 全体污染源收集通报机制唯有在非并发格局时才可用.
WinForm和Console应用都是默认为出现格局.
例如msdn上的特别例子程序,就需要在先后的app.config中充分

<configuration>
<runtime>
   <gcConcurrent enabled=”false” />
</runtime>
</configuration>

全文完. 谢谢各位!

参考文献References

Garbage Collection: Automatic Memory Management in the Microsoft .NET
Framework By Jeffrey Richter 
http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

Garbage Collection Part 2: Automatic Memory Management in the Microsoft
.NET Framework By Jeffrey Richter
http://msdn.microsoft.com/en-us/magazine/bb985011.aspx

Garbage Collector Basics and Performance Hints By Rico Mariani at
Microsoft  http://msdn.microsoft.com/en-us/library/ms973837.aspx

http://drowningintechnicaldebt.com/blogs/royashbrook/archive/2007/06/22/top-20-net-garbage-collection-gc-articles.aspx

Large Object Heap Uncovered By Maoni Stephens
http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

Garbage collection in msdn
http://msdn.microsoft.com/en-us/library/0xy59wtx.aspx

How does the GC work and what are the sizes of the different
generations?  By Tess Ferrandez 
http://blogs.msdn.com/tess/archive/2008/04/17/how-does-the-gc-work-and-what-are-the-sizes-of-the-different-generations.aspx

So, what’s new in the CLR 4.0 GC? By Maoni Stephens
http://blogs.msdn.com/maoni/archive/2008/11/19/so-what-s-new-in-the-clr-4-0-gc.aspx

Using GC Efficiently – Part 1
http://blogs.msdn.com/maoni/archive/2004/06/15/156626.aspx

Using GC Efficiently – Part 2
http://blogs.msdn.com/maoni/archive/2004/09/25/234273.aspx

Using GC Efficiently – Part 3
http://blogs.msdn.com/maoni/archive/2004/12/19/327149.aspx

Using GC Efficiently – Part 4
http://blogs.msdn.com/maoni/archive/2005/05/06/415296.aspx

The mystery of concurrent GC 
http://www.julmar.com/blog/mark/PermaLink,guid,3670d081-0276-48e6-b97d-1b644093b52e.aspx

http://blogs.msdn.com/clyon/archive/2004/09/10/228104.aspx

http://blogs.msdn.com/clyon/archive/2004/09/08/226981.aspx

http://msdn.microsoft.com/en-us/library/cc713687.aspx

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图