2016-06-01 3 views
3

У меня есть некоторый код, который я добавил вложенную словарю, в следующем форматеИспользование памяти словарей в C#

Dictionary<string, Dictionary<string, Dictionary<string, float>>> 

После этого я заметил, что использование памяти моего приложения взлетела ЗНАЧИТЕЛЬНО. Эти словари вводятся в строки, которые часто повторяются, и есть много таких словарей, порядка 10 тысяч.

Чтобы решить эту проблему, я предположил, что повторяющиеся струны питаются значительным объемом памяти. Мое решение было хэш строки и использовать целое число вместо (я бы держать одну копию таблицы радуги, так что я мог бы обратить хэш при необходимости)

Dictionary<int, Dictionary<int, Dictionary<int, float>>> 

Так что я пошел в профайлер памяти, чтобы увидеть, какого рода уменьшение размера я мог получить. К моему шоку я фактически обнаружил, что хранилище строк на самом деле меньше по размеру (как нормальное, так и включенное).

Это не меняет интуитивный смысл. Даже если компилятор достаточно умен, чтобы хранить только одну копию строки и использовать ссылку, я бы подумал, что ссылка будет указателем, который вдвое больше размера int. Я также не использовал никаких методов String.Intern, поэтому я не знаю, как это было бы выполнено (также есть String.Intern)?

Я очень смущен относительно того, что происходит под капотом, любая помощь было бы оценено

+3

Ничего особенного не делается под капотом. Либо ваша стратегия интернирования не удаляла много избыточности, либо была ошибка. Вам нужно отправить код. – usr

+1

Возможно, вы можете использовать словарь > ', чтобы избавиться от вложенности. «Словарь» - это не маленький тип. Используйте строковый кортеж. – usr

+2

"взлетел ЗНАЧИТЕЛЬНО". - по сравнению с чем? (Обратите внимание, что http: // stackoverflow.com/questions/20430157/memory-usage-of-dictionary-in-c-sharp можно использовать как дублирующую цель для вашего вопроса, если вы не уточните, как это не так) –

ответ

4

Если ваши ключи и значения являются объектами, для каждого элемента словаря имеется примерно 20 байт служебных данных, а также несколько байт на словарь. Это в дополнение к пространству, потребляемому ключами и значениями. если у вас есть типы значений как ключи и значения, то это 12 байт плюс пространство, потребляемое ключом и значением для каждого элемента в словаре. Это означает, что количество элементов равно внутренней емкости словаря. Но обычно есть больше возможностей, чем элементов, поэтому теряется пространство.

Взвешенное пространство будет, как правило, более высоким относительным процентом, если у вас много словарей с небольшим количеством элементов, чем если бы у вас был один словарь со многими элементами. Если я пойду по вашему комментарию, ваши словари с 8 элементами будут иметь вместимость 11, те с двумя элементами будут иметь 3, а те с 10 будут иметь значение 11.

Если я понимаю ваше гнездование counts, то один словарь верхнего уровня будет представлять собой 184 словарных элемента. Но если считать неиспользованную емкость, она приближается к 200 до объема пространства. 200 * 20 = 4000 байт для каждого словаря верхнего уровня. Сколько из них у вас есть? Вы говорите десятки тысяч из них в тысячах объектов. Каждые 10 000 будут потреблять около 38 МБ словаря накладные расходы. Добавьте к этому объекты, хранящиеся в словаре.

Возможное объяснение того, почему ваша попытка уменьшить его путем управления хэш-кодами будет, если не будет много дублированных ссылок на ваши ключи. Замена ссылочного ключа объекта ключом int не изменяет объем служебной информации словаря, и вы добавляете хранилище новой коллекции хеш-кодов.

Смежные вопросы