C#:new []似乎没有在Debug中分配内存

时间:2014-04-02 22:38:00

标签: c# memory optimization build

我尝试将大块内存分配为字节数组(400MB)

    public static void Main(string[] args)
    {
        const int MegaByte = 1048576;

        byte[] bytes = new byte[400 * MegaByte];

        for (int i = 0; i < bytes.Length; i++)
        {
            bytes[i] = 3;
        }

        Console.WriteLine("Total array length : {0}", bytes.Length);
        Console.WriteLine("First byte = '{0}' Last byte = '{1}'", bytes[0], bytes[bytes.Length - 1]);
        Console.Read();
    }

输出:

Total array length : 419430400
First byte = '3' Last byte = '3'

正如预期的那样,当我刚刚分配400MB内存时,我看到Windows任务管理器中正在使用的内存大幅跳转。但是,如果我将forloop用法替换为仅使用第一个和最后一个字节:

    public static void Main(string[] args)
    {
        const int MegaByte = 1048576;

        byte[] bytes = new byte[400 * MegaByte];

        bytes[0] = 0;
        bytes[bytes.Length - 1] = 2;

        Console.WriteLine("Total array length : {0}", bytes.Length);
        Console.WriteLine("First byte = '{0}' Last byte = '{1}'", bytes[0], bytes[bytes.Length - 1]);
        Console.Read();
    }     

输出:

Total array length : 419430400
First byte = '0' Last byte = '2'

即使分配的数组的长度被认为是相同的,也没有观察到已用内存的大跳跃。我假设如果我们构建在Debug中,就不会有这样的优化。在“调试”构建期间是否进行了一些优化,或者在编译IL时,这些事情是否会在较低级别进行优化?

2 个答案:

答案 0 :(得分:1)

调试/发布模式优化只是指令优化(IL - >本机代码编译,内联,指令重新排序等 - 除了常量使用的const折叠之外的所有内容)。这不会改变内存管理方式,只会改变代码流和内存访问方式。当您查看IL代码并将其与相应的汇编代码进行比较时,您可以看到这一点:大多数IL代码只定义了访问/使用内存的方式;分配和取消分配始终由GC管理(对于newobjnewarr等短名称。)

影响记忆行为的唯一方法是通过更改设置来影响GC。可以在此处找到GC的相关设置:http://msdn.microsoft.com/en-us/library/6bs4szyc(v=vs.110).aspx

因此,在所有情况下,内存由GC管理,它从内核中获取内存(我猜使用calloc)并释放内存(free)到内核。在您的情况下,分配内存(地址空间为数据保留),但未提交。一旦您访问了一个页面(4 KB),它就会被提交并显示出来。

答案 1 :(得分:0)

据我所知,调试和非调试版本之间的对象分配没有优化。

猜猜 - 您在任务管理器中看到的最有可能的数字是提交的页面,而在大型对象堆上分配大型数组可能只是保留地址空间并允许操作系统在访问时提交/零内存。你应该能够通过访问数组的每个4K元素来确认它。