Почему куча больших объектов и почему мы заботимся? - PullRequest
96 голосов
/ 21 января 2012

Я читал о Поколениях и куче больших объектов.Но я до сих пор не понимаю, каково значение (или выгода) наличия кучи больших объектов?

Что могло пойти не так (с точки зрения производительности или памяти), если бы CLR полагался только на поколение 2 (учитываячто порог для Gen0 и Gen1 мал для обработки больших объектов) для хранения больших объектов?

Ответы [ 5 ]

186 голосов
/ 21 января 2012

Сборка мусора не только избавляется от объектов, на которые нет ссылок, но и сжимает кучу.Это очень важная оптимизация.Это не только делает использование памяти более эффективным (без неиспользуемых отверстий), но и делает кэш-память процессора более эффективной.Для современных процессоров кэш-память представляет собой большую проблему, она на порядок проще, чем шина памяти.

Сжатие выполняется простым копированием байтов.Это, однако, требует времени.Чем крупнее объект, тем больше вероятность того, что стоимость его копирования превысит возможные улучшения использования кэша ЦП.

Поэтому они выполнили ряд тестов для определения точки безубыточности.И достигла 85 000 байтов в качестве точки отсечения, где копирование больше не улучшает производительность.За исключением двух массивов, они считаются «большими», когда массив содержит более 1000 элементов.Это еще одна оптимизация для 32-битного кода, распределитель кучи больших объектов обладает специальным свойством, которое распределяет память по адресам, которые выровнены по 8, в отличие от обычного распределителя поколений, который распределяет только по 4. Такое выравнивание является большой проблемой для двойногоЧтение или запись неверно выровненного двойника очень дорого.Как ни странно, в редкой информации Microsoft никогда не упоминаются массивы длинных, не уверенных, что с этим.

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

Проблема, которая в противном случае полностью исчезает при запуске кода в 64-разрядной операционной системе.,64-разрядный процесс имеет 8 терабайт доступного адресного пространства виртуальной памяти, на 3 порядка больше, чем 32-разрядный процесс.Вы просто не можете выбежать из дыр.

Короче говоря, LOH делает код более эффективным.За счет использования доступного адресного пространства виртуальной памяти менее эффективно.


UPDATE. NET 4.5.1 теперь поддерживает сжатие свойства LOH, GCSettings.LargeObjectHeapCompactionMode .Остерегайтесь последствий, пожалуйста.

8 голосов
/ 21 января 2012

Если размер объекта больше некоторого закрепленного значения (85000 байт в .NET 1), то CLR помещает его в кучу больших объектов.Это оптимизирует:

  1. Распределение объектов (мелкие объекты не смешиваются с большими объектами)
  2. Сборка мусора (LOH собирается только на полном GC)
  3. Дефрагментация памяти (LOH никогда редко уплотняется)
7 голосов
/ 21 января 2012

Существенным отличием кучи малых объектов (SOH) и кучи больших объектов (LOH) является то, что память в SOH сжимается при сборе, а LOH нет, как показывает эта статья . Уплотнение крупных объектов стоит дорого. Как и в примерах, приведенных в статье, скажем, что для перемещения байта в памяти требуется 2 цикла, а затем для сжатия 8-мегабайтного объекта в 2-ГГц компьютере требуется 8 мс, что является большой стоимостью. Учитывая, что крупные объекты (в большинстве случаев массивы) довольно распространены на практике, я полагаю, что именно поэтому Microsoft закрепляет большие объекты в памяти и предлагает LOH.

Кстати, согласно этой записи , LOH обычно не создает проблем с фрагментами памяти.

2 голосов
/ 21 января 2012

Принцип состоит в том, что маловероятно (и вполне возможно, что плохой дизайн), что процесс создаст много короткоживущих больших объектов, поэтому CLR выделяет большие объекты в отдельную кучу, на которой он запускает GC по другому расписанию для обычной кучи,http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

0 голосов
/ 21 января 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...