Почему сборщики мусора замораживают выполнение? - PullRequest
13 голосов
/ 30 ноября 2009

По дороге домой я думал о сборке мусора и начал задумываться: почему сборщик мусора полностью останавливает выполнение программы? Лично я разработал бы его, чтобы блокировать любые потоки, которые пытаются выделить новый объект, но работающие потоки остались бы одни. Я не могу представить ситуацию, когда это было бы проблемой по сравнению с тем, как работает сборщик мусора.

Ответы [ 5 ]

13 голосов
/ 19 июня 2012

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

В компоновке ГХ существует компромисс между задержкой и пропускной способностью. Вы можете либо обрабатывать блоки, выделенные в куче, индивидуально («инкрементно»), либо вы можете группировать их и обрабатывать все одновременно («остановите мир»). Полностью инкрементный сбор никогда не полностью замораживает программу и имеет очень низкую задержку, но также имеет очень низкую пропускную способность. Остановите мир, сборщики мусора имеют наихудшую возможную задержку (замораживание программы на несколько секунд или даже минут за раз), но почти оптимальную пропускную способность.

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

Простой алгоритм GC, который никогда не останавливается, см. Беговая дорожка Бейкера . Для получения дополнительной информации о сборке мусора я настоятельно рекомендую Справочник по управлению памятью и Справочник по сборке мусора .

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

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

Кико писал, что паузы необходимы для определения достижимости. Это тоже не правда. См. Исследование Дейкстры о коллекционерах «на лету» и любых недавних ГХ в реальном времени, таких как Stacatto .

Джерри Коффин написал лучший ответ, но переезд не причина, по которой GC останавливается. Есть GC, которые не двигаются, но делают паузу (например, HLVM), и те, которые двигаются, но не делают пауз (например, Stacatto ).

12 голосов
/ 30 ноября 2009

Современные сборщики мусора (в любом случае в .NET и Java) на самом деле не "останавливают мир" - они делают все умные вещи для одновременного сбора.

Однако вы можете рассмотреть ситуацию, подобную этой:

 object x = null;
 object y = new object();
 ...
 x = y;
 y = null;

Теперь предположим, что GC смотрит на x, затем строки ниже ... run, а затем GC смотрит на y - он не увидит никаких живых объектов ... кроме объекта должен еще быть живым.

По сути, для получения согласованного набора ссылок требуется определенное количество приостановок. Затем происходит уплотнение, переназначение ссылок и т. Д. Однако, это не так плохо, как раньше, когда требовалось остановить все на протяжении всего цикла GC. Это делает , однако, мне больно думать:)

6 голосов
/ 30 ноября 2009

В дополнение к тому, что сказал Кико Лобо, сборщики мусора могут также перемещать вещи в памяти.

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

Какая нить.

2 голосов
/ 30 ноября 2009

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

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

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

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

Редактировать: Возможно, вы захотите прочитать «1011» Пола Уилсона «Обзор методов сбора мусора в однопроцессорном режиме» . Это не является окончательным (особенно если учесть его возраст), но это как минимум разумная отправная точка.

1 голос
/ 30 ноября 2009

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

Если он не заморозил казнь, он не мог этого гарантировать.

...