【问题标题】:Array Allocation in .NET.NET 中的数组分配
【发布时间】:2013-01-27 19:15:31
【问题描述】:

问题是关于 .net 中数组的分配。我在下面有一个示例程序,其中我可以获得的最大数组是长度。我将长度增加到 +1,它给出了 outofMemory 异常。但是如果我保持长度并删除 cmets,我可以分配 2 个不同的大数组。两个数组都小于 .net 允许的 2 GB 对象大小,总内存也小于虚拟内存。有人可以提出任何想法吗?

 
class Program
    {
        static int length = 203423225;
        static double[] d = new double[length];
        //static int[] i = new int[15000000];
        static void Main(string[] args)
        {

            Console.WriteLine((sizeof(double)*(double)length)/(1024*1024));

            Console.WriteLine(d.Length);
            //Console.WriteLine(i.Length);
            Console.WriteLine(Process.GetCurrentProcess().VirtualMemorySize64.ToString());
        }
    }

【问题讨论】:

  • 您期待什么?最大数组大小取决于系统条件,并且您不断更改条件。
  • 如果它是为 32 位编译的,在 .NET 中你往往会出现 1.2-1.6GB 左右的内存不足错误;看到您正在创建大约 1.55GB 的双打,这并不奇怪。有关更多信息,请参阅:stackoverflow.com/questions/1087982/…
  • 您正在尝试分配更多内存,然后才被允许。一个整数是 32 位的,但您正在查看 64 位虚拟内存大小,您的代码没有意义。
  • 那么您是否正在尝试解决现实世界的问题,或者您只是对内存管理感到好奇?两者都可以 - 只是好奇这里是否有更多上下文。

标签: c# .net gcallowverylargeobjects


【解决方案1】:

32 位进程必须从可用的地址空间为数组分配虚拟内存。默认为 2 GB。其中包含代码和数据的混合。分配是根据现有分配之间的漏洞进行的。

这样的分配总是失败不是因为没有剩余的虚拟内存,而是因为可用的空洞不够大而失败。而且您要求一个大漏洞,获得 1.6 吉字节是非常罕见的,并且仅适用于不加载任何额外 DLL 的非常简单的程序。基础差的 DLL 是一种将大洞一分为二的好方法,从而大大降低了这种分配成功的几率。更典型的首次尝试工作分配约为 650 兆字节。第二次分配没有失败,因为还有另一个可用的孔。在程序运行一段时间并且地址空间变得碎片化之后,几率会大大降低。 90 MB 的分配可能会失败。

您可以了解如何使用 SysInternals 的 VMMap 实用程序为程序划分虚拟内存地址空间。

一个简单的解决方法是将 EXE 项目的平台目标设置设置为 AnyCPU 并在 64 位操作系统上运行程序。它将有大量可用的可寻址虚拟内存空间,您只会受到页面文件的最大允许大小和 .NET 2 GB 对象大小限制的限制。 .NET 4.5 中使用新的<gcAllowVeryLargeObjects> 配置元素解决了一个限制。即使是 32 位程序也可以通过 editbin.exe 的 /LARGEADDRESSAWARE 选项在 64 位操作系统上利用可用的 4 GB 32 位地址空间,您必须在构建后事件中运行它。

【讨论】:

    【解决方案2】:

    这是因为在为数组分配内存时,内存必须是连续的(即数组必须作为一大块内存分配)。即使总共有足够的空间来分配数组,如果空闲地址空间被分割,那么内存分配仍然会失败,除非这些空闲空间中最大的一个足够大以容纳整个数组。

    【讨论】:

    • 这似乎是有效的,但我有一个疑问。 .net 中的托管堆不是连续内存。
    猜你喜欢
    • 2014-08-20
    • 1970-01-01
    • 2018-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多