Размер памяти .NET

У меня есть довольно простой вопрос о хранении данных и его памяти.

У меня есть List<t>, в котором хранятся базовые объекты, которые мне нужны. Тип t имеет int id, чтобы определить его вместе с другими полями.

Теперь у меня есть словарь. Если я создаю Dictionary<t, int>, где t является объектом для значения, будет ли распределение памяти намного выше, если я создам Dictionary<int, int>, то есть копия t-объекта будет сохранена или будет только привязка к t снова сохранить?

Спасибо

Ответ 1

Это зависит от того, что T. Если T является ссылочным типом (то есть a class), тогда в словаре будет храниться только ссылка. Если T - тип значения (a struct), то копия будет сохранена.

Ответ 2

Типы ссылок не создают повторяющиеся объекты, когда вы их передаете. Под обложками, в основном, вы обходите указатели. Поэтому, если у вас есть N объектов, у вас будет N x память на объект + память, необходимая для ссылки на каждый объект. Это независимо от контейнера хранения для этих ссылок, в вашем случае, словаря. Вы понесете некоторую стоимость памяти для словаря, но если вы создали еще один словарь и поместили в него все те же объекты, у вас было бы только 2x расходы на память словаря плюс один набор объектов в памяти. Это когда вы используете ссылочные типы.

MyObject object = new MyObject();  // one object created in memory
MyObject object2 = object; // still only one object created in memory, but we have two references now

Типы значений всегда уникальны в памяти. Поэтому, если вы создаете словарь System.Int32, а затем создаете дубликат словаря, вы также будете иметь копию каждого значения в словаре.

int myInt = 5; // one int created in memory
int myInt2 = myInt; // two ints have been created in memory

Итак, давайте выясним, какие блоки памяти выделены для определенных сценариев:

// two value types
Dictionary<int, int> myDictionary1 =  
1 x Dictionary
N x int <key>
N x int <value>

Dictionary<int, int> myDictionary1 + 
Dictionary<int,int> myDictionary2 (clone of 1) =
2 x Dictionary
2N x int <key>
2N x int <value>

// reference types
Dictionary <string, MyObject> myDictionary3 = 
1 x Dictionary
N x string Reference
N x string instance (if they are all unique)
N x Object Reference
N x Object instance (if they are all unique)

Dictionary <string, MyObject> myDictionary3 +
Dictionary <string, MyObject> MyDictionary4 (clone of 3) =
2 x Dictionary
2N x string reference
1N x string instance (if they are all unique)
2N x Object reference
1N x Object instance (if they are all unqiue)

Вы сценарий:

Dictionary<int, MyObject> myDictionary5
1 X Dictionary
N X key
N X value reference
N X value object

Dictionary<int, MyObject> myDictionary5 + 
Dictionary<int, MyObject> myDictionary6 (clone of 5) =
2 x Dictionary
2N x key
2N x value reference
1N x value objects

Ответ 3

Сохраняется только ссылка на ваш объект. Распределение памяти будет небольшим.

Ответ 4

Я предполагаю, что вы говорите о конкретном типе коллекции System.Collections.Generic.Dictionary<K,V>.

Вы не сказали нам, является ли ваш тип 't' типом значения или ссылочным типом.

Если это ссылочный тип, например, class T { int id; ...}, то Dictionary<K,T> будет содержать ссылки на добавленные вами объекты.

Если это тип значения, например. struct T { int id; ...}, то Dictionary<K,T> сохранит копии добавленных значений.

Счастливый взлом.

Ответ 5

Как я упоминал в другом вопросе для профилирования памяти при разработке, вы можете использовать этот код:

bool forceFullCollection = false;

Int64 valTotalMemoryBefore = System.GC.GetTotalMemory(forceFullCollection);

//call here your bulk of Dictionary operations and objects allocations

Int64 valTotalMemoryAfter = System.GC.GetTotalMemory(forceFullCollection);

Int64 valDifferenceMemorySize = valTotalMemoryAfter - valTotalMemoryBefore;

О параметре forceFullCollection: "Если параметр forceFullCollection равен true, этот метод ждет короткий интервал перед возвратом, когда система собирает мусор и завершает объекты. Длительность интервала - это внутренний заданный предел по количеству циклов сбора мусора и изменению объема памяти, восстановленного между циклами. Сборщик мусора не гарантирует, что будет собрана вся недоступная память". Метод GC.GetTotalMemory

Удачи!;)