字典计数大于 89478457 时出错

Error when Dictionary count is bigger as 89478457

我正在执行此命令

Dictionary<UInt64, int> myIntDict = new Dictionary<UInt64, int>(89478458);

这个错误:

System.OutOfMemoryException was unhandled  HResult=-2147024882
Message=Array dimensions exceeded supported range.
Source=mscorlib
StackTrace:
   at System.Collections.Generic.Dictionary`2.Initialize(Int32 capacity)
   at System.Collections.Generic.Dictionary`2..ctor(Int32 capacity, IEqualityComparer`1 comparer)

89478457上没有报错。这是 Dictionary.cs 中 Initialize 的来源:

    private void Initialize(int capacity)
    {
        int size = HashHelpers.GetPrime(capacity);
        ...
        entries = new Entry[size];
        ...
    }

当我重现这个时,错误发生在创建数组时。在这种情况下,条目是一个大小为 24 的结构。当我们得到最大 int32 (0x80000000-1) 并除以 24 = 89478485 时,这个数字介于素数 89478457 和 89478503 之间。

这是否意味着结构数组不能大于 maxInt32/sizeOfThisStruct?

编辑:

是的。我实际上超过了 2 GB。当字典创建 struct Entry 的内部数组时,(键,值)对存储在哪里,就会发生这种情况。在我的例子中,sizeof(Entry) 是 24 个字节,并且值类型是内联分配的。

解决方案是使用 gcAllowVeryLargeObjects flag (thank you Evk). Actually in .net core the flag is the environment variable COMPlus_gcAllowVeryLargeObjects (thank you svick).

是的,Paparazzi 是对的。我不得不考虑,如何不浪费内存。 谢谢你们。

.NET 运行时存在已知限制 - 堆上允许的最大对象大小为 2 GB,即使在 64 位版本的运行时也是如此。但是,从 .NET 4.5 开始,有 configuration option 允许您放宽此限制(仍然仅在 64 位版本的运行时上)并创建更大的数组。启用的配置示例是:

<configuration>
  <runtime>
    <gcAllowVeryLargeObjects enabled="true" />
  </runtime>
</configuration>

表面上看字典没有意义
您只能有 int 唯一值
你真的有我的副本吗

UnInt32 变为 4,294,967,295
你为什么要浪费 4 个字节?

89,478,458 行 当前一行为 12 字节
您在大约 83,333,333 行有 1 GB
由于一个对象需要连续内存 1 GB 是一个实际限制

if values 真的是 strut 24
然后 31,250,000 中有 1 GB

这只是一个非常大的集合

您可以将其拆分为多个集合

或者使用 class,因为它只是一个参考,我认为是 4 个字节