Что такое сборщик мусора garbage collector на базовом уровне

Сборка мусора, управление памятью и указатели

Сборщик мусора в C#

Ранее в теме Типы значений и ссылочные типы мы рассматривали отдельные типы данных и как они располагаются в памяти. Так, при использовании переменных типов значений в методе, все значения этих переменных попадают в стек. После завершения работы метода стек очищается.

При использовании же ссылочных типов, например, объектов классов, для них также будет отводиться место в стеке, только там будет храниться не значение, а адрес на участок памяти в хипе или куче, в котором и будут находиться сами значения данного объекта. И если объект класса перестает использоваться, то при очистке стека ссылка на участок памяти также очищается, однако это не приводит к немедленной очистке самого участка памяти в куче. Впоследствии сборщик мусора (garbage collector) увидит, что на данный участок памяти больше нет ссылок, и очистит его.

В методе Test создается объект Country. С помощью оператора new в куче для хранения объекта CLR выделяет участок памяти. А в стек добавляет адрес на этот участок памяти. В главном методе Main мы вызываем метод Test. И после того, как Test отработает, место в стеке очищается, а сборщик мусора очищает ранее выделенный под хранение объекта country участок памяти.

Сборщик мусора не запускается сразу после удаления из стека ссылки на объект, размещенный в куче. Он запускается в то время, когда среда CLR обнаружит в этом потребность, например, когда программе требуется дополнительная память.

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

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

Кроме того, чтобы снизить издержки от работы сборщика мусора, все объекты в куче разделяются по поколениям. Всего существует три поколения объектов: 0, 1 и 2-е.

Когда сборщик мусора приступает к работе, он сначала анализирует объекты из поколению 0. Те объекты, которые остаются актуальными после очистки, повышаются до поколения 1.

Если после обработки объектов поколения 0 все еще необходима дополнительная память, то сборщик мусора приступает к объектам из поколения 1. Те объекты, на которые уже нет ссылок, уничтожаются, а те, которые по-прежнему актуальны, повышаются до поколения 2.

Поскольку объекты из поколения 0 являются более молодыми и нередко находятся в адресном пространстве памяти рядом друг с другом, то их удаление проходит с наименьшими издержками.

Класс System.GC

Рассмотрим некоторые методы и свойства класса System.GC:

Метод Collect приводит в действие механизм сборки мусора. Перегруженные версии метода позволяют указать поколение объектов, вплоть до которого надо произвести сборку мусора

Метод GetGeneration(Object) позволяет определить номер поколения, к которому относится переданый в качестве параметра объект

Метод GetTotalMemory возвращает объем памяти в байтах, которое занято в управляемой куче

Метод WaitForPendingFinalizers приостанавливает работу текущего потока до освобождения всех объектов, для которых производится сборка мусора

Работать с методами System.GC очень просто:

Default : значение по умолчанию для данного перечисления (Forced)

Forced : вызывает немедленное выполнение сборки мусора

Optimized : позволяет сборщику мусора определить, является ли текущий момент оптимальным для сборки мусора

Источник

Базовые сведения о времени жизни объекта

Размещайте объект в управляющей куче с помощью ключевого слова new и забывайте об этом.

После создания объект будет автоматически удалён сборщиком мусора, когда в нём отпадёт надобность. Сразу возникает вопрос о том, каким образом сборщик мусора определяет, когда в объект отпадает необходимость?

Давайте просмотрим простой пример:

Обратите внимание, что ссылка на объект Car(myCar) была создана непосредственно внутри метода MakeACar() и не передавалась за пределы определяющей области действия (ни в виде возвращающегося значения, ни в виде параметров ref/out). По этому после вызова метода ссылка на myCar окажется недостижимой, а объект Car — кандидатом на удаление сборщиком мусора. Следует, однако, понимать, что нет никакой гарантии на удаление объекта сразу после выполнение метода MakeACar(). Всё, что в данный момент можно предполагать, так это то, что когда в CLR-среде будет в следующий раз проводиться сборка мусора, то объект myCar будет поставлен на удаление.

Программистам на C++ хорошо известно, что если они специально не позаботятся об удалении размещённых в куче объектов, вскоре обязательно начнут возникать «утечки памяти». На самом деле отслеживание проблем, связанных с проблемой утечки памяти, являются одним из самых утомительных и длинных аспектов программирования в неуправляемых средах.

Роль корневых элементов приложения

Во время процессы сборки мусора исполняющая среда будет исследовать объекты в куче, чтобы определить, являются ли они по прежнему достижимыми (т.е. корневыми) для приложения. Для этого среда CLR будет создавать графы объектов, представляющие все достижимые для приложения объекты. Кроме того, следует иметь ввиду, что сборщик мусора никогда не будет создавать граф для одного и того же объекта дважды, избегая необходимости выполнения подсчёта циклических ссылок, который характерен для программирования в среде COM.

Поколения объектов

Чем дольше объект находится в куче, тем выше вероятность того, что он там будет оставаться.

Поколения 0 и 1 называются эфемерными.

Сборщик мусора сначала анализирует все объекты, которые относятся к поколению 0. Если после их удаления остаётся достаточное количество памяти, статус всех уцелевших объектов повышается до поколения 1. Если все объекты поколения 0 были проверены, но всё равно требуется дополнительное пространство, то будет запцщени проверка объектов поколения 1. Объекты этого поколения, которым удалось уцелеть, станут объектами поколения 2. если же сборщику мусора всё равно понадобится память, что сборке мусора подвергнуться объекты поколения 2. Так как объектов выше 2 поколения не бывает, то статус объектов не изменится.
Из всего вышесказанного можно сделать вывод, что более новые объекты будут удалятся быстрее, нежели более старые.

Источник

Garbage Collector & C++

Ручное управление памятью с С++ — одновременно один из самых больших плюсов и минусов в языке. Действительно, эта парадигма позволяет создавать очень производительные программы, однако она же рождает и кучу проблем. Существует несколько способов избавится от них. Я попробовал несколько и в итоге пришел к сборщику мусора. В этой статье я хочу изложить не столько реализацию сборщика мусора на С++, сколько историю идеи и его использования, каково им пользоваться и почему в итоге от него отказался.

Итак, как у большинства программистов у меня есть свой проект, а именно двумерный игровой движок. На нем и производились все «эксперименты».

Этап первый: отладка памяти

Самая часто встречающаяся проблема при ручном управлении памятью — это утечки. Чтобы узнать о них нужно следить за памятью. Именно таков и был мой первоначальных подход. Следим за созданием и удалением объектов, проверяем после завершения программы что осталось не удаленным. Делается очень просто: перегружаем операторы new и delete, чтобы они могли принимать в параметрах имя файла исходного кода и строчку, откуда происходит аллокация, и храним все аллокации в одном месте. Для удобства объявляем макрос, который и передает имя файла и строку в оператор. Соответственно при удалении объекта удаляем запись о соответствующей аллокации.

Этап второй: умные указатели

И правда же, самое распространенное решение проблемы управления памятью — умные указатели. О них вас обязательно спросят на собеседовании. Идея проста: вместо обычных указателей мы используем шаблонные классы, которые работают как указатели, но имеют дополнительный функционал для автоматического освобождения объектов. Вместе с объектом храним счетчик ссылок, при присваивании значения указателю увеличиваем счетчик, при уничтожении указателя — уменьшаем. Если счетчик равен нулю — объект никому не нужен и его можно освободить. Однако, есть небольшая проблема — если два объекта ссылаются друг на друга, они никогда не будут освобождены, так как у обоих счетчик ссылок равен единице.

Что такое сборщик мусора garbage collector на базовом уровне. Смотреть фото Что такое сборщик мусора garbage collector на базовом уровне. Смотреть картинку Что такое сборщик мусора garbage collector на базовом уровне. Картинка про Что такое сборщик мусора garbage collector на базовом уровне. Фото Что такое сборщик мусора garbage collector на базовом уровне

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

Что такое сборщик мусора garbage collector на базовом уровне. Смотреть фото Что такое сборщик мусора garbage collector на базовом уровне. Смотреть картинку Что такое сборщик мусора garbage collector на базовом уровне. Картинка про Что такое сборщик мусора garbage collector на базовом уровне. Фото Что такое сборщик мусора garbage collector на базовом уровне

Что ж, давайте придумаем ситуацию посложнее.

Что такое сборщик мусора garbage collector на базовом уровне. Смотреть фото Что такое сборщик мусора garbage collector на базовом уровне. Смотреть картинку Что такое сборщик мусора garbage collector на базовом уровне. Картинка про Что такое сборщик мусора garbage collector на базовом уровне. Фото Что такое сборщик мусора garbage collector на базовом уровне

Такую ситуацию тоже можно разрешить с помощью слабых/сильных указателей, но будет ли это легче ручного управления? Если программист что-то сделает неправильно, результат будет такой же: утекший неосвобожденный объект. На самом деле, такие ситуации встречаются редко и в целом такой подход значительно упрощает работу с памятью.

Этап третий: велосипедостроительство

Опробовав умные указатели, я остался неудовлетворен. Просто хочется использовать один у тот же тип умного указателя везде и не задумываться о зацикленных ссылках. Пусть он сам о них задумывается. Но как это сделать? Представим ситуацию:

Что такое сборщик мусора garbage collector на базовом уровне. Смотреть фото Что такое сборщик мусора garbage collector на базовом уровне. Смотреть картинку Что такое сборщик мусора garbage collector на базовом уровне. Картинка про Что такое сборщик мусора garbage collector на базовом уровне. Фото Что такое сборщик мусора garbage collector на базовом уровне

Нужно как-то узнать что два нижних объекта зациклены и их можно удалить, ведь на них никто не ссылается. По рисунку уже несложно догадаться: если ссылки от объекта не ведут к верхнеуровневым объектам, значит он может быть освобожден. Верхнеуровневые объекты — это, грубо говоря, те объекты, с которых начинается инициализация приложения. Для С++ это объекты на стеке и статические.

Этап четвертый: сборщик мусора

Думаю, внимательный читатель уже понял, что это и есть схема работы сборщика мусора, только наоборот. Самый простой сборщик работает примерно так: спускаясь по ссылкам от верхнеуровневых объектов помечаем всех как актуальные, после этого мы имеем право удалить те, что оказались не помеченными.

Что такое сборщик мусора garbage collector на базовом уровне. Смотреть фото Что такое сборщик мусора garbage collector на базовом уровне. Смотреть картинку Что такое сборщик мусора garbage collector на базовом уровне. Картинка про Что такое сборщик мусора garbage collector на базовом уровне. Фото Что такое сборщик мусора garbage collector на базовом уровне

Для реализации нам потребуется такой же шаблонный класс указателя, как и в случае с умными указателями. Плюс нужен сам сборщик, который будет за всем следить и производить собственно сборку мусора.

Для каждого созданного объекта создается мета-информация ObjectInfo и хранится в менеджере памяти MemoryManager. Каждый такой объект создается перегруженным оператором new. ObjectInfo хранит в себе информацию о размере объекта, месте, откуда он был создан, список указателей на него и указатель на функцию для вызова деструктора этого объекта.

Для работы с объектами вместо привычных указателей используются шаблонные классы Ptr и RootPtr. RootPtr необходим для обозначения верхнеуровневых объектов, так как в ходе выполнения программы невозможно узнать что объект создан на стеке или статически (поправьте меня, если я не прав). При инициализации или копировании указателей происходит добавление и удаление указателей из соответствующих ObjectInfo.

При вызове сборки мусора меняется булевая переменная маркера на противоположную и начинается цикл отметки объектов. Цикл проходит по верхнеуровневым указателям, затем рекурсивно по их дочерним указателям. Дочерний указатель — это тот, что находится в теле объекта. После этого все объекты, у которых маркер не совпадает с текущим удаляются.

Внимательный читатель наверняка заметил еще одно — за удобство мы платим производительностью. Мы получаем все типичные минусы сборщиков мусора: излишний расход памяти и большое время работы сборки мусора. Именно на моем проекте игрового движка это фатальный минус, ведь на каждый кадр должно уходить несколько миллисекунд и просто нет времени чтобы все остановить и произвести сборку мусора. Однако, есть и хороший момент, этот сборщик мусора полностью наш и мы можем делать все что захотим!

Этап пятый: импровизация

Первое что приходит в голову — это то, что мы полностью управляем моментом сборки мусора. Совсем не обязательно делать это посреди геймплея. Можно сделать это как раз тогда, когда и происходит наибольшее количество инициализаций и уничтожений объектов, во время загрузки уровней. При разработке игр не принято делать много аллокаций/уничтожений во время активной игры. Если при каждом выстреле загружать и создавать объект пули, никакая оптимизация памяти вас не спасет. Поэтому делать долгую сборку мусора между уровнями кажется довольно живучей идеей.

Следующая идея — вовсе не вызывать сборку мусора или делать это крайне редко. Объекты по-прежнему удалять вручную или умными указателями, а сборщик мусора можно использовать в роли отладчика и подстраховки. В таком варианте мы получим производительность эквивалентную ручному управлению памятью и безопасность от утечек при сборке мусора.

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

Помимо этого можно реализовать еще немного «вкусностей». Так как мы используем шаблонные классы-указатели, мы можем проверять их на корректность, то есть при удалении объекта вручную делать все ссылки на него невалидными. И далее в нужных местах их проверять. Еще одно из возможных улучшений — это дефрагментация памяти. На этапе сборки мусора можно перерасположить актуальные объекты в памяти для уменьшения кеш-промахов процессора, что несомненно даст прирост производительности.

Этап шестой: возврат к началу

В конце концов на решение об отказе от сборщика повлияла специфика моего проекта. Проект планируется с открытым исходным кодом и он нацелен прежде всего на удобство использования. Усложнение и без того сложного синтаксиса С++ специфичными указателями и добавление сборщика мусора несомненно плохо повлияют на проект. Просто представьте знакомство разработчика с новой технологией: ему необходимо изучать новое API да еще и с мудреной моделью управления памятью, тем более, что большинство программистов С++ и так неплохо управляются с памятью вручную.
Окончательно я убедился в возврате к ручной модели когда принял решение использовать скрипты. Именно они нужны для простоты и удобства. Делаешь прототип или простую игру — используй скрипты, экономь время и ресурсы. Необходима гибкость и производительность — добро пожаловать в С++. Тем, кто будет использовать С++ на самом деле вряд ли понадобится сборщик мусора.

Вот так я и вернулся к началу. Надеюсь мой опыт будет полезен или хотя бы интересен другим велосипедостроителям.

Источник

Что такое сборщик мусора garbage collector на базовом уровне. Смотреть фото Что такое сборщик мусора garbage collector на базовом уровне. Смотреть картинку Что такое сборщик мусора garbage collector на базовом уровне. Картинка про Что такое сборщик мусора garbage collector на базовом уровне. Фото Что такое сборщик мусора garbage collector на базовом уровнеКДПВ

В реальности все оказалось гораздо сложнее. Сборщик мусора, конечно, помогает избежать наиболее распространенных утечек из тех, что встречаются в неуправляемых программах, утечек, которые возникают из-за того, что разработчик забыл освободить выделенную память, когда работа с ней закончена. Автоматическая сборка мусора также решает проблему преждевременного освобождения памяти, хотя способ решения этой проблемы может и сам привести к утечкам, ведь у сборщика может быть свое, особое мнение на то, является ли объект еще «живым» и в какой момент его необходимо удалить. И чтобы мы могли со всем этим справиться, необходимо понять, как работает сборщик мусора.

Как работает сборщик мусора

Так как же все-таки работает магия сборщика мусора? Основная идея довольно проста — он изучает, как объекты размещены в памяти, определяя те из них, до которых может добраться запущенная программа, следуя некоторой цепочке ссылок.

Когда начинается сборка мусора, сборщик просматривает набор ссылок, называемых корнями. Это участки памяти, которые в силу определенных причин должны быть доступны всегда, и которые содержат ссылки на объекты, созданные программой. Сборщик помечает эти объекты как живые, а затем просматривает все объекты, на которые они ссылаются, помечая живыми и их. Сборщик мусора продолжает в том же духе, пока не пометит живыми все объекты, которые он смог найти таким способом.

Сборщик мусора определяет объект как ссылающийся на другой объект, если он или один из его предков имеет поле, содержащее ссылку на другой объект.

Локальные переменные ссылочного типа в методе, который выполняется в данный момент.

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

Управляемые объекты, переданные в неуправляемую библиотеку через Interop.

Если управляемый объект передается в неуправляемую библиотеку COM+ через Interop, то он станет корневым объектом с подсчетом ссылок. Это происходит потому, что COM+ не выполняет сборку мусора. Вместо этого он использует систему подсчета ссылок. Как только библиотека COM+ завершает работу с объектом, устанавливая счетчик ссылок в 0, он перестает быть корневым и может быть удален.

Ссылки на объекты с финализатором.

Граф объектов

Все становится еще более запутанным, когда в игру вступают циклические ссылки.

Что такое сборщик мусора garbage collector на базовом уровне. Смотреть фото Что такое сборщик мусора garbage collector на базовом уровне. Смотреть картинку Что такое сборщик мусора garbage collector на базовом уровне. Картинка про Что такое сборщик мусора garbage collector на базовом уровне. Фото Что такое сборщик мусора garbage collector на базовом уровнеГраф связей между объектами и корнями (корни обозначены как «GC root»)

При разработке приложений программистам часто удобнее представлять память организованной в дерево, начинающееся с отдельных корней:

Что такое сборщик мусора garbage collector на базовом уровне. Смотреть фото Что такое сборщик мусора garbage collector на базовом уровне. Смотреть картинку Что такое сборщик мусора garbage collector на базовом уровне. Картинка про Что такое сборщик мусора garbage collector на базовом уровне. Фото Что такое сборщик мусора garbage collector на базовом уровнеДревовидное представление связей относительно корня GC root 2

Что такое сборщик мусора garbage collector на базовом уровне. Смотреть фото Что такое сборщик мусора garbage collector на базовом уровне. Смотреть картинку Что такое сборщик мусора garbage collector на базовом уровне. Картинка про Что такое сборщик мусора garbage collector на базовом уровне. Фото Что такое сборщик мусора garbage collector на базовом уровнеДревовидное представление связей относительно объекта ClassC

Реальные приложения, особенно с компонентами пользовательского интерфейса, имеют гораздо более сложные графы, чем в примерах выше. Даже на такую простую вещь, как label в диалоговом окне, можно ссылаться из огромного количества различных мест:

Что такое сборщик мусора garbage collector на базовом уровне. Смотреть фото Что такое сборщик мусора garbage collector на базовом уровне. Смотреть картинку Что такое сборщик мусора garbage collector на базовом уровне. Картинка про Что такое сборщик мусора garbage collector на базовом уровне. Фото Что такое сборщик мусора garbage collector на базовом уровнеПример древовидного представления связей относительно объекта в реальном проекте

В таком лабиринте может запросто потеряться какой-нибудь объект.

Ограничения сборщика мусора

Неиспользуемые объекты, на которые все еще есть ссылки

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

Фрагментация кучи

Производительность сборщика мусора

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

Режимы работы сборщика мусора

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

Поколения сборщика мусора

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

Заключение

Примечание переводчика

Источник

Сборка мусора рабочей станции и сборка мусора сервера

Сборщик мусора является самонастраивающимся и может работать в широком диапазоне сценариев. Но вы можете задать тип сборки мусора на основе характеристик рабочей нагрузки. Среда CLR предоставляет следующие виды сборки мусора.

Сборка мусора на рабочей станции выполняется для клиентских приложений. Это вариант по умолчанию для автономных приложений. Для размещенных приложений, например размещаемых в ASP.NET, разновидность сборки мусора по умолчанию определяется узлом.

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

На рисунке ниже показаны выделенные потоки, выполняющие сборку мусора на сервере.

Что такое сборщик мусора garbage collector на базовом уровне. Смотреть фото Что такое сборщик мусора garbage collector на базовом уровне. Смотреть картинку Что такое сборщик мусора garbage collector на базовом уровне. Картинка про Что такое сборщик мусора garbage collector на базовом уровне. Фото Что такое сборщик мусора garbage collector на базовом уровне

Особенности производительности

Сборщик мусора рабочей станции

Ниже приведены замечания по сборке мусора рабочей станции, касающиеся потоков и производительности.

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

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

Сборщик мусора сервера

Ниже приведены замечания по сборке мусора сервера, касающиеся потоков и производительности.

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

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

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

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

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *