C# 背景GC:Troelsen

C# 背景GC:Troelsen,c#,.net,memory-leaks,garbage-collection,clr,C#,.net,Memory Leaks,Garbage Collection,Clr,我刚刚在网上读了一个话题,我有点困惑 因此,“Pro C#5.0和.NET 4.5框架”-安德鲁·特罗尔森。引述: class Program { static void Main(string[] args) { Console.WriteLine("***** Fun with System.GC *****"); // Print out estimated number of bytes on heap. Console.W

我刚刚在网上读了一个话题,我有点困惑

因此,“Pro C#5.0和.NET 4.5框架”-安德鲁·特罗尔森。引述:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("***** Fun with System.GC *****");
        // Print out estimated number of bytes on heap.
        Console.WriteLine("Estimated bytes on heap: {0}",
        GC.GetTotalMemory(false));
        // MaxGeneration is zero based.
        Console.WriteLine("This OS has {0} object generations.\n",
        (GC.MaxGeneration + 1));
        Car refToMyCar = new Car("Zippy", 100);
        Console.WriteLine(refToMyCar.ToString());
        // Print out generation of refToMyCar.
        Console.WriteLine("\nGeneration of refToMyCar is: {0}",
        GC.GetGeneration(refToMyCar));
        // Make a ton of objects for testing purposes.
        object[] tonsOfObjects = new object[50000];
        for (int i = 0; i < 50000; i++)
            tonsOfObjects[i] = new object();
        // Collect only gen 0 objects.
        GC.Collect(0, GCCollectionMode.Forced);
        GC.WaitForPendingFinalizers();
        // Print out generation of refToMyCar.
        Console.WriteLine("Generation of refToMyCar is: {0}",
        GC.GetGeneration(refToMyCar));
        // See if tonsOfObjects[9000] is still alive.
        if (tonsOfObjects[9000] != null)
        {
            Console.WriteLine("Generation of tonsOfObjects[9000] is: {0}",
            GC.GetGeneration(tonsOfObjects[9000]));
        }
        else
            Console.WriteLine("tonsOfObjects[9000] is no longer alive.");
        // Print out how many times a generation has been swept.
        Console.WriteLine("\nGen 0 has been swept {0} times",
        GC.CollectionCount(0));
        Console.WriteLine("Gen 1 has been swept {0} times",
        GC.CollectionCount(1));
        Console.WriteLine("Gen 2 has been swept {0} times",
        GC.CollectionCount(2));
        Console.ReadLine();
    }
}

public class Car
{
    public int CurrentSpeed { get; set; }
    public string PetName { get; set; }

    public Car()
    {
    }

    public Car(string name, int speed)
    {
        PetName = name;
        CurrentSpeed = speed;
    }

    public override string ToString()
    {
        return string.Format("{0} is going {1} MPH", PetName, CurrentSpeed);
    }
}
在这一点上,我希望您对对象生命周期的细节感到更舒服。在下一节中,我们将进一步研究垃圾收集过程,讨论如何构建可终结对象以及一次性对象。请注意,只有在构建维护内部非托管资源的C#类时,通常才需要以下技术

为什么他说CLR在后台执行了大量GC?他是说对象从0代升级到第1代,还是说当应用程序关闭时将收集这些对象?AFAIK在这一点上(在exit Main方法之前)GC只运行了一次,因为我们只有一个显式GC,但隐式GC是不可能的,因为我们正在调用方法。所以,如果我们调用对象的方法,它们肯定是非收集的,如果我们不调用,我们就无法在环境中了解它们。输出还说0代收集了一次,所以他为什么告诉我们执行了多少次GC

我喜欢人们写一些奇怪的、毫无根据的东西,但在说了
之后,很明显,
绝对清晰,那是
等等

好的,我正在增加数组大小,但现在输出是:

***** Fun with System.GC *****
Estimated bytes on heap: 37748
This OS has 3 object generations.

Zippy is going 100 MPH

Generation of refToMyCar is: 0
Generation of refToMyCar is: 0
Generation of tonsOfObjects[9000] is: 0

Gen 0 has been swept 1 times
Gen 1 has been swept 1 times
Gen 2 has been swept 1 times
代码:

static void Main()
{
Console.WriteLine(“*******Fun with System.GC****”);
//打印出堆上的估计字节数。
WriteLine(“堆上的估计字节:{0}”,
GC.GetTotalMemory(假));
//MaxGeneration是基于零的。
Console.WriteLine(“此操作系统有{0}个对象生成。\n”,
(GC.MaxGeneration+1));
Car refToMyCar=新车(“Zippy”,100);
Console.WriteLine(refToMyCar.ToString());
//打印出refToMyCar的生成。
Console.WriteLine(“\n refToMyCar的生成为:{0}”,
GC.GetGeneration(refToMyCar));
//为测试目的制作大量对象。
object[]tonsOfObjects=新对象[5000000];
对于(int i=0;i<50000;i++)
tonsOfObjects[i]=新对象();
//仅收集第0代对象。
GC.Collect(0,GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
//打印出refToMyCar的生成。
WriteLine(“refToMyCar的生成为:{0}”,
GC.GetGeneration(refToMyCar));
//查看tonsOfObjects[9000]是否仍处于活动状态。
if(tonsOfObjects[9000]!=null)
{
WriteLine(“tonsOfObjects[9000]的生成为:{0}”,
GC.GetGeneration(tonsOfObjects[9000]);
}
其他的
WriteLine(“tonsOfObjects[9000]不再处于活动状态。”);
//打印出一代人被扫荡了多少次。
Console.WriteLine(“\nGen 0已扫描{0}次”,
GC.CollectionCount(0);
WriteLine(“Gen 1已扫描{0}次”,
GC.收集计数(1);
WriteLine(“Gen 2已扫描{0}次”,
GC.收集计数(2);
Console.ReadLine();
}

怎么可能呢?我们有一个GC,但对象并没有升级到第一代

您只创建了价值一磅的对象。你有没有在原代码上抄近路?一些你在汽车课上做过的证明


要创建大量的对象,您需要创建至少2兆字节的对象才能触发gen#0收集。任意改变50000到500000,使之足够。用不同的值进行实验,看看对显示的数字有什么影响。

汽车类别可能不同,但输出也是从原始来源提供的,因此他说,该输出包含有关的所有必需信息。现在的汽车等级是原装的(改装的)嗯,他错了。从结果中可以明显看出。请做一个实验,重现观察结果是非常容易的。我照你说的做了,但现在输出比以前更奇怪
***** Fun with System.GC *****
Estimated bytes on heap: 37748
This OS has 3 object generations.

Zippy is going 100 MPH

Generation of refToMyCar is: 0
Generation of refToMyCar is: 0
Generation of tonsOfObjects[9000] is: 0

Gen 0 has been swept 1 times
Gen 1 has been swept 1 times
Gen 2 has been swept 1 times
 static void Main()
    {
        Console.WriteLine("***** Fun with System.GC *****");
        // Print out estimated number of bytes on heap.
        Console.WriteLine("Estimated bytes on heap: {0}",
        GC.GetTotalMemory(false));
        // MaxGeneration is zero based.
        Console.WriteLine("This OS has {0} object generations.\n",
        (GC.MaxGeneration + 1));
        Car refToMyCar = new Car("Zippy", 100);
        Console.WriteLine(refToMyCar.ToString());
        // Print out generation of refToMyCar.
        Console.WriteLine("\nGeneration of refToMyCar is: {0}",
        GC.GetGeneration(refToMyCar));
        // Make a ton of objects for testing purposes.
        object[] tonsOfObjects = new object[5000000];
        for (int i = 0; i < 50000; i++)
            tonsOfObjects[i] = new object();
        // Collect only gen 0 objects.
        GC.Collect(0, GCCollectionMode.Forced);
        GC.WaitForPendingFinalizers();
        // Print out generation of refToMyCar.
        Console.WriteLine("Generation of refToMyCar is: {0}",
        GC.GetGeneration(refToMyCar));
        // See if tonsOfObjects[9000] is still alive.
        if (tonsOfObjects[9000] != null)
        {
            Console.WriteLine("Generation of tonsOfObjects[9000] is: {0}",
            GC.GetGeneration(tonsOfObjects[9000]));
        }
        else
            Console.WriteLine("tonsOfObjects[9000] is no longer alive.");
        // Print out how many times a generation has been swept.
        Console.WriteLine("\nGen 0 has been swept {0} times",
        GC.CollectionCount(0));
        Console.WriteLine("Gen 1 has been swept {0} times",
        GC.CollectionCount(1));
        Console.WriteLine("Gen 2 has been swept {0} times",
        GC.CollectionCount(2));
        Console.ReadLine();
    }