Подтвердить что ты не робот

Использование памяти между 32-битным пулом и 64-битным пулом

У нас есть приложение ASP.NET, построенное на основе MonoRail и NHibernate, и я заметил странное поведение между ними при работе с 64-битным или 32-разрядным режимом. Все скомпилировано как AnyCPU и отлично работает с обоими режимами, но использование памяти сильно отличается.

Посмотрите на следующие снимки из ANTS:

32bit_snapshot: enter image description here

против

64bit_snapshot: enter image description here

Сценарий использования для обоих снимков в значительной степени эквивалентен (я попал на те же страницы на обоих запусках).

Во-первых, почему неиспользуемая память настолько высока в 64-битном режиме? И почему неуправляемая память будет в 4 раза больше в 64-битном режиме?

Любое понимание этого было бы действительно полезно.

4b9b3361

Ответ 1

Первоначальное распределение памяти для 64-битного процесса намного выше, чем для эквивалентного 32-битного процесса.

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

Эта статья: http://blogs.msdn.com/b/maoni/archive/2007/05/15/64-bit-vs-32-bit.aspx дает более подробное объяснение.

Более высокое неуправляемое использование памяти, которое вы видите, вероятно, связано с тем, что объекты .NET, работающие в 32-битном режиме, используют минимум 12 байтов (8 байтов + 4 байта), тогда как один и тот же объект в 64-битном случае будет принимать 24 байты (12 байтов + 8 байтов).

Еще одна статья, чтобы полностью объяснить это: http://www.simple-talk.com/dotnet/.net-framework/object-overhead-the-hidden-.net-memory--allocation-cost/

Ответ 2

Стандартный ответ на проблемы с памятью в 64-разрядных системах заключается в том, что большинство операций с памятью по умолчанию выровнены с 16 байтами. Ожидается, что память, считываемая в/из 128-битных регистров XXM, будет совпадать с границами 16 байт. Два параметра в стеке занимают тот же объем памяти, что и три (адрес возврата занимает 8 байтов). Gnu malloc выравнивает выделенные области до 16 байтовых границ.

Если размер выделенных единиц мал, тогда накладные расходы будут огромными: сначала накладные расходы на выравнивание данных, а затем накладные расходы на выравнивание бухгалтерии, связанной с данными.

Также я бы предсказал, что в 64-битных системах структуры данных эволюционировали: вместо бинарных или 2-3-4, сбалансированных, игровых или любых деревьев, возможно, имеет смысл иметь radix 16 деревьев, которые могут иметь много слабины, но может быть быстро обработано с расширениями SSE, которые гарантированно будут там.

Ответ 3

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

В числах ваш 32-битный процесс может выделять только 1gig, а 64-разрядный может выделить всю вашу память. В 32-битном процессе GC начнет очистку раньше, потому что ваша программа будет страдать от производительности, когда она использует большую память. CLR в 64-битном процессе начнет очистку, когда ваша общая системная память опустится ниже определенной корзины.