По дороге домой я думал о сборке мусора, и мне стало интересно, почему сборщик мусора полностью останавливает выполнение программы?
В компоновке ГХ существует компромисс между задержкой и пропускной способностью. Вы можете либо обрабатывать блоки, выделенные в куче, индивидуально («инкрементно»), либо вы можете группировать их и обрабатывать все одновременно («остановите мир»). Полностью инкрементный сбор никогда не полностью замораживает программу и имеет очень низкую задержку, но также имеет очень низкую пропускную способность. Остановите мир, сборщики мусора имеют наихудшую возможную задержку (замораживание программы на несколько секунд или даже минут за раз), но почти оптимальную пропускную способность.
Все основные производственные GC сегодня обеспечивают золотую середину, как правило, со сбором поколений с поколениями питомников на каждую ветвь, собираемыми партиями, и инкрементным или одновременным сбором общего старого поколения. Таким образом, паузы собраны только в детских коллекциях, а размер питомника ограничен, поэтому время паузы поддерживается на низком уровне, например 10-100мс в .NET с рабочей станцией GC.
Простой алгоритм GC, который никогда не останавливается, см. Беговая дорожка Бейкера . Для получения дополнительной информации о сборке мусора я настоятельно рекомендую Справочник по управлению памятью и Справочник по сборке мусора .
В других ответах здесь много дезинформации. Джон Скит написал некоторый исходный код и начал обсуждать его с точки зрения сборки мусора. Вы должны быть очень осторожны при этом, потому что между исходным кодом и тем, что видит GC, мало соответствия Компилятор выполняет перестановки блоков команд, распределение регистров, продвижение и т. Д., Которые влияют на то, что видно для GC во время выполнения. В частности, область действия в исходном коде не переносится в скомпилированный код и обычно заменяется связанной концепцией liveness . Джон также написал, что вы должны сделать паузу, чтобы получить глобальные корни. Это не совсем верно, хотя это наиболее эффективный способ получения глобальных корней, и получающаяся в результате пауза почти всегда крошечна (менее миллисекунды), потому что вы просто копируете менее чем килобайт стека из каждого потока.
Powerlord написал, что движущиеся коллекторы должны блокировать чтение и, следовательно, все потоки, которые читают. Это тоже не правда. Простейшим примером счетчика являются неизменяемые данные: ссылочная прозрачность означает, что вы можете безопасно читать из любой копии.
Кико писал, что паузы необходимы для определения достижимости. Это тоже не правда. См. Исследование Дейкстры о коллекционерах «на лету» и любых недавних ГХ в реальном времени, таких как Stacatto .
Джерри Коффин написал лучший ответ, но переезд не причина, по которой GC останавливается. Есть GC, которые не двигаются, но делают паузу (например, HLVM), и те, которые двигаются, но не делают пауз (например, Stacatto ).