В .NET вы можете установить генерацию объекта GC или иным образом указать, что он собирается выйти из области видимости? - PullRequest
0 голосов
/ 02 марта 2019

.NET сборщик мусора - это сборщик мусора поколений, основанный на философии, согласно которой большинство выделенных объектов являются недолговечными.Таким образом, объекты начинаются в «поколении 0», где их можно легко собрать (и часто это делают), а объекты с более долгим сроком службы переводятся в «поколение 1» и «поколение 2», где их затрагивают более полные развертки.Объекты поколения 0 часто создаются, когда метод выделяет объект как часть его состояния, а затем позволяет этому объекту выходить из области видимости при выходе.

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

Было бы неплохо, на данный момент, иметь возможность сообщить об этом сборщику мусора.сказать, что да, этот объект существовал в течение длительного времени, но вскоре он может быть удален, и сборщик мусора может ответить, переместив объект в кучу gen 0.Затем, в следующий раз, когда потребуется выполнить сборку мусора (например, при следующем вызове этого долгосрочного метода), необходимую память можно восстановить с более быстрой разверткой gen 0 вместо полной, блокирующей очистки, таким образом уменьшаянепредсказуемость влияния сборщика мусора на производительность.

Некоторая другая информация:

  • В настоящее время моя команда устраняет эту проблему непредсказуемой производительности, храня эти объекты "локального состояния" в гигантскихизменяемые структуры, которые передаются через параметры ref и in.Насколько я понимаю, .NET Framework плохо оптимизирован для любых структур, за исключением небольшого количества байтов (официальные источники говорят 16, хотя я слышал 24), а также изменяемых структур, но я не могу спорить с тем фактом, чтоэти структуры имеют автоматическую область видимости и, безусловно, будут освобождены при возврате метода - если, конечно, мы не сможем сообщить GC о выходе класса.
  • Я был бы совершенно счастлив, если бы это былAPI предложения, а не команда, поскольку в конечном итоге GC должен делать то, что должен.Возможно, если выяснится, что объект еще где-то имел ссылку, это может привести к некоторому снижению производительности.
  • Я также открыт для ответов об этой функции, существующей в средах сборки мусора, отличных от .NET.

Ответы [ 2 ]

0 голосов
/ 15 марта 2019

Фундаментальный принцип работы сборщиков мусора в .NET и Java заключается в том, что до тех пор, пока память не будет полностью повреждена, никогда не будет возможно наблюдать ненулевую ссылку, которая не идентифицирует живой объект.Если в .NET Framework или виртуальной машине Java была включена функция для явного освобождения связанной с управляемой GC ссылки, они должны были бы убедиться, что никаких наблюдаемых ссылок на объект нигде не существует, прежде чем он сможет перезапустить хранилище.Поскольку такая гарантия будет стоить примерно столько же, сколько цикл сбора мусора, а цикл GC может освободить хранилище для объекта без необходимости ссылки на него, возможность «ручного» удаления объекта редко добавляет многозначение.

0 голосов
/ 04 марта 2019

Простой ответ на ваш вопрос - нет, такого API нет.Большинство современных ГХ спроектированы с учетом «гипотезы поколений», что большинство объектов умирают молодыми или живут долго.То, что вы описываете, обычно называют «кризисом среднего возраста» - объекты, живущие достаточно долго, чтобы перейти в старшее поколение, но сразу же больше не нужны.Это, очевидно, далеко не оптимально для современных ГХ.Распространенный способ избежать этого состоит в том, чтобы: уменьшить распределение (меньше шансов быть продвинутым, поэтому мы часто остаемся в части "умри молодым") или повторно использовать объекты (таким образом мы приземляемся в части "живи долго").

Byмногократно используя структуры и ссылки, вы выбрали первый подход.Вы также можете подумать о повторном использовании объектов путем объединения, например ArrayPool<T> или других.

Что касается вопросов, вы предлагаете API для:

"сборщика мусора, который может ответить перемещениемobject to the gen 0 heap "

Несмотря на то, что он сильно затрагивает возможные детали реализации, вряд ли можно реализовать его эффективно.Многие GC, в том числе .NET, стараются изо всех сил не копировать / перемещать память.Поколения - это просто логические области памяти, границы которых перемещаются взад и вперед.Таким образом, «перемещение объекта в gen0» потребует его копирования (и, возможно, всего его сохраненного графа, чтобы сделать его разумным), что приведет к накладным расходам, значительно превышающим потенциальную выгоду.Хуже того, в настоящее время это может быть сделано только во время GC, так как у нас не реализовано одновременное сжатие (в общем, перемещение объектов во время их использования).

"Как я понимаю, платформа .NETплохо оптимизирован для любых структур, кроме небольшого числа байтов (официальные источники говорят 16, хотя я слышал 24), а также для изменяемых структур "

Это выглядит как небольшая ложь.Среда выполнения .NET значительно оптимизирует использование структур, и если вы передаете их по ref, это один из наиболее эффективных подходов, которые я могу придумать.Просто знайте только о ловушке защитного копирования , с которой вы можете столкнуться при использовании in параметров.

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