如何知道可以分配给定类型的.net数组的ACTUAL最大元素数?

时间:2009-12-03 15:10:50

标签: .net arrays 64-bit large-object-heap

我知道.net中的所有数组都限制为2 GB,在这个前提下,我尽量不在数组中分配更多的n =((2 ^ 31) - 1)/ 8。尽管如此,这些元素的数量似乎仍然无效。任何人都知道如何在运行时确定给定sizeof(T)的元素的最大数量?

我知道无论接近这个数字的数量是多少元素,但是,无论出于什么意图和目的,让我说我需要它。

注意:我在64位环境中,为我的AnyCPU应用程序提供目标平台,并且RAM中至少有3100 MB空闲。

更新 谢谢大家的贡献,抱歉,我很安静。对于给您带来的不便,我深表歉意。我无法重述我的问题,但我可以补充一点,我正在寻找的是解决这样的问题:

template <class T>
array<T>^ allocateAnUsableArrayWithTheMostElementsPossible(){
    return gcnew array<T>( ... );
}

我自己的答案中的结果是有点令人满意但不够好。此外,我没有在另一台机器上测试它(很难找到另一台机器超过4 GB)。此外,我一直在做自己的研究,似乎没有廉价的方法来计算这个在运行时。无论如何,这只是一个加分,我正在尝试完成的用户都不能期望使用我试图在没有容量的情况下实现的功能。

因此,换句话说,我只想了解为什么数组的最大元素数不能达到2GB ceteris paribus 。我现在只需要一个最大值。

5 个答案:

答案 0 :(得分:2)

答案 1 :(得分:2)

所以,我运行了一个li'l程序来找出一些硬值,这就是我发现的:

  • 给定类型T,f(sizeof(T))= N + d

    • 其中f是实际最大尺寸 一系列的Ts。
    • N是理论上的 最大尺寸,即: Int32 :: MaxValue / sizeof(T)
    • 和d,是N和f(x)之间的差异。

结果:

  • f(1)= N - 56
  • f(2)= N - 28
  • f(4)= N - 14
  • f(8)= N - 7
  • f(16)= N -3
  • f(32)= N - 1

我可以看到,每次尺寸重复时,实际尺寸和理论尺寸之间的差异都会折叠,但不会超过2的强度。任何想法为什么?

修改:dT个元素的数量。要以字节为单位查找d,请执行sizeof(T) * d

答案 2 :(得分:0)

您的进程空间限制为2GB,除非您[编译了anycpu或x64]并在[x64计算机上]的x64进程中运行。这是你可能真正遇到的。无论如何,计算过程中的净空并不是一门精确的科学。

(Nitpickers转角:有一个/ 3GB开关和其他边缘情况的堆栈会对此产生影响。此外,该过程还需要分配虚拟或物理空间。重点是,目前,大多数人们将经常遇到每个进程限制的操作系统,而不是任何.NET限制)

答案 3 :(得分:0)

更新: 我的other answer contains the solution但我留下来了解有关Mono,C#,CLR链接和讨论主题的信息

数组的最大大小受整数大小的限制,而不受其包含的对象大小的限制。但.NET中的任何对象都限制为2GB,周期(感谢Luke并参见EDIT),它限制了数组的总大小,这是各个元素的总和加上一些开销。

它扼杀你的系统的原因是系统的可用内存。而win32进程的系统只允许你使用2GB的内存,你的程序和CLR在你启动数组之前已经使用了很多内存。您可以用于阵列的其余部分:

int alot = 640000000;
byte[] xxx = new byte[1U << 31 - alot];

这取决于您的CLR配置方式是否内存不足。例如,在ASP.NET下,默认情况下绑定到计算机总可用内存的60%。

编辑:This answer to a related post更深入探讨了主题和64位问题。它可以在64位系统上运行,但只能使用变通方法。它指向this excellent blog post on the subject,其中解释了BigArray<T>

注1:其他CLR,即Mono,只允许大于2GB的物体。

注2:它不是限制你的语言。这在C#中编译得很好,但是尝试并且没有抛出它的机器是一个相当未来的想法(坦率地说,Array类中保持长度的字段是int,这意味着这将是总是抛出32位,但不一定,但极有可能,在任何64位实现上):

int[] xxx = new int[0xFFFFFFFFFFFFFFFF];  // 2^64-1

答案 4 :(得分:-1)

您还需要将指针大小(System.IntPtr.Size)添加到每个sizeof(T),以考虑指向任何给定数组元素中对象的指针。