Как обрабатываются большие объекты в сборщике мусора .NET
Что проверяют
Знаете ли вы про отдельную кучу больших объектов и понимаете ли, чем опасна её фрагментация.
Как отвечать
Объекты больше 85 000 байт (а также массивы double от 1000 элементов) размещаются не в обычной куче, а в куче больших объектов. Порог настраиваемый, но по умолчанию такой.
Особенности, из-за которых это важно:
- собирается только вместе с поколением 2, то есть при полной сборке. Полные сборки редкие и дорогие, поэтому большой объект живёт заметно дольше, чем ожидаешь;
- по умолчанию не уплотняется. Обычная куча после сборки сдвигает объекты, убирая дыры. Здесь этого не делается, потому что копирование мегабайтных блоков дорого. Отсюда фрагментация: свободной памяти в сумме много, а непрерывного куска нужного размера нет, и вы получаете
OutOfMemoryExceptionпри внешне свободной памяти; - уплотнение можно запросить вручную через
GCSettings.LargeObjectHeapCompactionModeперед принудительной сборкой. Это тяжёлая операция и применяется как редкая мера, а не регулярно.
Что делать на практике, и это главная часть ответа:
- не создавать большие массивы часто. Классический источник это буферы под чтение файлов и сетевых потоков, а также укрупняющиеся списки, которые при росте создают всё более крупные внутренние массивы;
- переиспользовать буферы через
ArrayPool<T>.Sharedвместо выделения нового массива на каждую операцию. Это самый действенный приём; - обрабатывать потоком, а не целиком: читать файл частями, а не загружать его в память;
Span<T>иMemory<T>для работы с участком без копирования;- при известном итоговом размере задавать ёмкость заранее, чтобы список не переползал через порог несколько раз.
Полезно упомянуть, что в серверном режиме сборщика поведение отличается: куч несколько, по числу ядер, и паузы распределяются иначе.
Где спотыкаются
Не знают про отдельную кучу и порог в 85 000 байт.
Считают, что нехватка памяти означает исчерпание всей памяти процесса.
Выделяют новый буфер на каждый запрос вместо пула.
Вызывают принудительную сборку в надежде решить проблему.