2016-05-30 5 views
0

Я получаю по этой командеОшибка при Словарь счетчик больше, как 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 нет никакой ошибки. Вот источник Initialize в Dictionary.cs:

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

Когда я воспроизвожу это, ошибка происходит на создании массива. Запись - это структура в этом случае с размером 24. Когда мы получаем max int32 (0x80000000-1) и делим на 24 = 89478485, и это число находится между простыми числами 89478457 и 89478503.

Означает ли это, что массив структуры не может быть больше как maxInt32/sizeOfThisStruct?

EDIT:

Да. Я действительно перехожу на 2 ГБ. Это происходит, когда словарь создает внутренний массив struct Entry, где хранятся пары (ключ, значение). В моем случае sizeof (Entry) - 24 байта, а тип значения - встроенный.

И решение должно использовать флаг gcAllowVeryLargeObjects (спасибо Evk). Фактически в ядре .net флаг равен the environment variable COMPlus_gcAllowVeryLargeObjects (спасибо svick).

И да, Paparazzi является правильным. Я должен думать о том, как не потерять память. Спасибо всем.

+0

Интересно, почему вам нужен словарь, что большие по размеру?Настоящая практичность этого испытания - это то, что я допрашиваю –

+0

@BenPhilipp Int - только для теста. На самом деле это структура. – Mottor

+0

@MukeshAdhvaryu Что вы будете использовать для разреженного 3D-массива. – Mottor

ответ

7

Известно ограничение среды выполнения .NET. Максимальный размер объекта, допустимый для кучи, составляет 2 ГБ, даже в 64-битной версии среды выполнения. Но, начиная с .NET 4.5, есть configuration option, что позволяет вам ослабить этот предел (только на 64-битной версии времени выполнения) и создать большие массивы. Пример конфигурации для того, чтобы это:

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

Одинаково ли это для .Net Core? Я думаю, что .Net Core не использует app.config. – svick

+3

См. Также [этот ответ] (http://stackoverflow.com/a/37423015/41071). – svick

+0

Спасибо за информацию. Кажется, ваша ссылка отвечает на ваш вопрос. Я тестировал и без этого варианта поведение кажется одинаковым (поэтому он также выбрасывает OutOfMemoryException при распределении слишком большого массива). – Evk

0

На поверхности словаря не имеет смысла
Вы можете иметь только ИНТ уникальные значения
У вас действительно есть, что мои дублирует

UnInt32 идет на 4294967295
Почему вы тратите 4 байта?

89,478,458 строк В настоящее время строка 12 байт
У вас есть 1 ГБ около 83333333 строк
Поскольку объект нуждается в непрерывной памяти 1 ГБ больше практического предела

Если значения действительно стойки 24
Тогда 1 гб в 31,250,000

это просто очень большая коллекция

Вы можете разделить вверх на более чем один Collectio п

Или использовать класс, как и тогда это просто ссылка с я думаю 4 байта

+0

В кодировке UInt64 в трехмерном массиве (X, Y, Z) значение представляет собой значение в массиве. Они заполнены динамически от пользователя (SQL), и массив разрежен. Тогда есть много расчетов. – Mottor

+0

Затем я предлагаю более эффективную кодировку, поскольку вы тратите много места. – Paparazzi

+0

Он закодирован с битовой маской. В реальности нормальный размер составляет от 100000 до 500000, но я должен знать, где предел, потому что я ничего не знаю о данных во время компиляции. – Mottor