Почему сборщики мусора замораживают исполнение?
Я думал о сборке мусора по дороге домой, и я начал задаваться вопросом, почему сборщик мусора полностью замораживает выполнение программы? Лично я бы запрограммировал его, чтобы заблокировать любые потоки, которые пытаются выделить новый объект, но потоки, которые были запущены, будут оставлены в покое.
Я не могу представить себе ситуацию, когда это будет проблемой по сравнению с тем, как работает сборщик мусора.
Ответы
Ответ 1
Современные сборщики мусора (в .NET и Java, во всяком случае) на самом деле не "останавливают мир" - они делают всевозможные умные вещи, чтобы собирать одновременно.
Однако вы можете рассмотреть такую ситуацию:
object x = null;
object y = new object();
...
x = y;
y = null;
Теперь предположим, что GC смотрит на x
, тогда строки ниже ...
выполняются, а затем GC смотрит на y
- он не будет видеть никаких живых объектов... но объект должен все еще остаются в живых.
В принципе, для получения последовательного набора ссылок необходимо определенное количество пауз. Затем происходит уплотнение, переназначение ссылок и т.д. Однако это не так плохо, как раньше, когда требуется, чтобы все было остановлено для всего цикла GC. Однако ему становится больно думать о:)
Ответ 2
Я думал о сборке мусора по дороге домой, и я начал задаваться вопросом, почему сборщик мусора полностью замораживает выполнение программы?
В проекте GC имеется компромисс между задержкой и пропускной способностью. Вы можете обрабатывать блоки, выделенные кучей, индивидуально ( "incremental" ), или вы можете их загружать и обрабатывать одновременно ( "остановить мир" ). Полностью инкрементная коллекция никогда полностью не замораживает программу и имеет очень низкую задержку, но также имеет очень низкую пропускную способность. Остановка мирового сборщика мусора имеет наихудшую возможную задержку (замораживание программы в течение секунд или даже минут за раз), но почти оптимальная пропускная способность.
Сегодня все основные производственные GC обеспечивают средний уровень, как правило, с коллекцией поколений с отдельными поколениями питомников, собранными партиями, и инкрементной или параллельной коллекцией старого старого поколения. Таким образом, только коллекции детского питания несут паузы и размер детского сада ограничены, поэтому время паузы остается низким, например. 10-100 мс в .NET с рабочей станцией GC.
Для простого алгоритма GC, который никогда не останавливается, см. Bread Treadmill. Для получения дополнительной информации о сборке мусора я настоятельно рекомендую Справочник по управлению памятью и Мусор Коллекционное руководство.
В других ответах здесь много дезинформации. Джон Скит написал некоторый исходный код и начал обсуждать его с точки зрения сбора мусора. Вы должны быть очень осторожны, потому что между исходным кодом и тем, что видит GC, мало соответствует. Компилятор выполняет перестановку блоков команд, распределение регистров, продвижение по службе и т.д., Все из которых влияют на то, что видно на GC во время выполнения. В частности, объем исходного кода не переносится на скомпилированный код и обычно заменяется связанной концепцией жизнеспособности. Джон также написал, что вы должны сделать паузу, чтобы получить глобальные корни. Это не совсем верно, хотя это самый эффективный способ получить глобальные корни, и результирующая пауза почти всегда крошечная (субмиллисекунда), потому что вы просто копируете меньше, чем kB стека из каждого потока.
Powerlord написал, что движущиеся сборщики должны блокировать чтение и, следовательно, все прочитанные потоки. Это также неверно. Простейшим примером счетчика являются неизменные данные: ссылочная прозрачность означает, что вы можете безопасно читать любую копию.
Кико написал, что для определения достижимости необходимы паузы. Это также неверно. См. Исследование Dijkstra о коллекторах "на лету" и любых недавних GC в реальном времени, таких как Stacatto.
Джерри Коффин написал лучший ответ, но движение не является причиной, по которой GCs приостанавливается. Есть GC, которые не двигаются, но делают паузу (например, HLVM) и те, которые перемещаются, но не останавливаются (например, Stacatto).
Ответ 3
В дополнение к тому, что сказал Кико Лобо, сборщики мусора также могут перемещать вещи в памяти.
Следовательно, они не просто должны блокировать потоки, которые записывают в память, а также потоки, которые читаются из памяти.
Это каждый поток.
Ответ 4
Большинство GC прекращают выполнение, потому что объекты могут перемещаться в памяти во время цикла сбора (по крайней мере, с наиболее разумно недавними проектами). Это означает, что при чтении или записи почти любого объекта в неподходящее время может возникнуть проблема.
Существуют коллекторы, которые были разработаны вокруг идеи просто блокировать чтение (или запись) в определенные части памяти, которые изменяются в данный момент времени, при условии, что выполнение использует только объекты, которые не являются (в настоящее время) движется, он может беспрепятственно двигаться. Проблема в том, что большинство типичных аппаратных средств не обеспечивают эффективной поддержки для этого, поэтому, хотя они работают в принципе, они практически неэффективны на практике. По крайней мере, одна попытка адаптировать этот тип алгоритма для использования защиты от записи, доступной в типичном пейджинговом блоке, но я не знаю, что он использовался для других целей, кроме исследований и экспериментов.
Первичная альтернатива заключается в том, чтобы сделать сборщик инкрементным - то есть заставить его выполнять только небольшое количество работы за раз, поэтому, даже если другое выполнение останавливается, оно должно останавливаться на некоторое время в любой момент времени.
Однако, когда многоядерные машины становятся настолько распространенными, я ожидаю увидеть больше работы, введенной в алгоритмы сбора мусора, которые могут выполняться параллельно с другим исполнением. До недавнего времени основное внимание уделялось минимизации общего времени/усилий, затраченных на сбор мусора. Растущее количество доступных сердечников, по-видимому, может (часто) означать, что выполнение более полной работы в сборке мусора может быть легко оправдано, если это позволяет основному ходу кода работать с меньшим количеством помех.
Изменить: вам может понадобиться прочитать Пол Уилсон Обзор методов обработки однопроцессорных мусора. Это не является окончательным (особенно больше, учитывая его возраст), но это, по крайней мере, разумная отправная точка.
Ответ 5
Потому что единственный способ убедиться, что рефери, который он собирается очистить, не используется кем-либо еще.
Если бы это не затормозило выполнение, это не могло заверить.