C# 如何获得总堆分配?GC.GetAllocatedBytesForCurrentThread()不';我做不到

C# 如何获得总堆分配?GC.GetAllocatedBytesForCurrentThread()不';我做不到,c#,.net-core,garbage-collection,C#,.net Core,Garbage Collection,我想知道一个线程累计分配了多少内存。从它的文档来看,GC.GetAllocatedBytesForCurrentThread()似乎是要使用的东西,但实际上,它给了我。。。还有别的 这是我的测试程序,使用dotnet core 3.1控制台应用程序Visual Studio模板创建 using System; class Program { static void Main() { long start, difference; start = GC.

我想知道一个线程累计分配了多少内存。从它的文档来看,
GC.GetAllocatedBytesForCurrentThread()
似乎是要使用的东西,但实际上,它给了我。。。还有别的

这是我的测试程序,使用dotnet core 3.1控制台应用程序Visual Studio模板创建

using System;

class Program {
    static void Main() {
        long start, difference;

        start = GC.GetAllocatedBytesForCurrentThread();
        var x = new int[1_000_000];
        difference = GC.GetAllocatedBytesForCurrentThread() - start;
        Console.WriteLine("{0} bytes allocated for array construction", difference);

        start = GC.GetAllocatedBytesForCurrentThread();
        Console.WriteLine(DateTime.Now.ToString());
        difference = GC.GetAllocatedBytesForCurrentThread() - start;
        Console.WriteLine("{0} bytes allocated for date printing", difference);
    }
}
它给了我这个输出

0 bytes allocated for array construction
9/17/2020 11:26:40 AM
19040 bytes allocated for date printing
Press any key to continue . . .
我不相信不在堆上分配一个字节就可以创建一百万个元素的数组

那么,有没有一种方法可以跟踪线程的堆分配?这个方法到底在做什么,如果有的话

这里有一个更长、更全面的测试程序,包括到目前为止的所有建议。我包含了sum部分,以验证在代码运行时是否确实创建了数组

using System;
using System.Linq;

class Program {
    static void Main() {
        long start, difference;

        {
            start = GC.GetAllocatedBytesForCurrentThread();
            var x = new int[1_000_000];
            x[^1] = 7;
            difference = GC.GetAllocatedBytesForCurrentThread() - start;
            Console.WriteLine("{0} bytes thread allocated for array construction (sum: {1})", difference, x.Sum());
        }

        start = GC.GetAllocatedBytesForCurrentThread();
        Console.WriteLine(DateTime.Now.ToString());
        difference = GC.GetAllocatedBytesForCurrentThread() - start;
        Console.WriteLine("{0} bytes thread allocated for date printing", difference);

        {
            start = GC.GetTotalMemory(true);
            var x = new int[1_000_000];
            x[^1] = 7;
            difference = GC.GetTotalMemory(true) - start;
            Console.WriteLine("{0} bytes total allocated for array construction (sum: {1})", difference, x.Sum());
        }

        start = GC.GetTotalMemory(true);
        Console.WriteLine(DateTime.Now.ToString());
        difference = GC.GetTotalMemory(true) - start;
        Console.WriteLine("{0} bytes total allocated for date printing", difference);

    }
}
输出:

0 bytes thread allocated for array construction (sum: 7)
9/17/2020 11:51:54 AM
19296 bytes thread allocated for date printing
4000024 bytes total allocated for array construction (sum: 7)
9/17/2020 11:51:54 AM
64 bytes total allocated for date printing                                                                              

通过以下IL代码进行阵列分配:

// int[] array = new int[1000000];
IL_0008: ldc.i4 1000000
IL_000d: newarr [mscorlib]System.Int32
IL_0012: stloc.2
阅读没有提供很多帮助的内容:

但可能数组是由CLR中的另一个线程创建的,事实上是由CLR线程本身创建的,我认为这就是为什么
GC.GetAllocatedBytesForCurrentThread()-start
返回
0
,而使用
GetTotalMemory
返回正确和真实的数量

数组在堆中分配,而本地值类型和引用直接在方法堆栈中创建

例如:

.locals init (
    [0] int64 'value'
)

IL_0001: ldc.i4.s 10
IL_0003: conv.i8
IL_0004: stloc.0
因此,在所有情况下,当前线程都不会消耗任何东西

但是,例如,如果您创建一个
列表
,然后添加一些项目,或者执行任何消耗内存的操作,比如调用medthods(
DateTime.Now.ToString()
),线程将消耗内存,您将看到使用
GetAllocatedBytesForCurrentThread
方法


但是在数组的情况下,如果是CLR线程创建了它们,我们看不到这一点。

如果使用
GC.GetTotalMemory(true)
而不是方法,会得到什么?我在.NET4.7.2(VS2017)上获得了约4MB的内存。这给了我更合理的数字,但似乎还包括其他线程。这个最小复制没有任何其他线程,但如果可能的话,我想在不那么琐碎的场景中使用此技术。我无法在我的计算机上进行测试,但您是否尝试更改一些单元格,因为这里您对数组不做任何操作。。。也许这就是GetAllocatedBytesForCurrentThread看到0的原因。@OlivierRogier既不接触数组,也不将数组馈送给
GC。KeepAlive
做任何事情。分配一个容量为1m的
列表
需要32个字节。我想知道如果您这样做会发生什么?