Подтвердить что ты не робот

Сбор мусора и нитки

AFAIK, когда GC делает свою вещь, VM блокирует все запущенные потоки - или, по крайней мере, когда он уплотняет кучу. Это относится к современным реализациям CLR и JVM (производственные версии по состоянию на январь 2010 года)? Пожалуйста, не предоставляйте основные ссылки на GC, поскольку я понимаю рудиментарные работы.

Я предполагаю, что глобальная блокировка выполняется так же, как когда происходит уплотнение, ссылки могут быть недопустимыми в течение периода перемещения, и кажется простым просто заблокировать всю кучу (т.е. косвенно, заблокировав все потоки). Я могу представить себе более надежные механизмы, но KISS часто преобладает.

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

  • Если это действительно так, то как тяжелые корпоративные двигатели, такие как JBOSS и Glassfish, поддерживают стабильно высокий уровень TPS? Я сделал некоторые поисковые запросы на JBOSS, и я ожидал найти что-то в APACHE, таком как распределитель памяти, подходящий для веб-обработки.

  • Перед лицом архитектур NUMA-esque (возможно, в ближайшем будущем) это звучит как катастрофа, если процессы не являются ЦП, связанными потоком и распределением памяти.

4b9b3361

Ответ 1

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

О да, и стоит отметить, что многие современные сборщики не имеют фаз уплотнения per se. Скорее они работают, копируя живые объекты в новое "пространство" и обнуляя старое "пространство", когда они сделаны.

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

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

... и остерегайтесь, что найти точные, подробные, публичные описания внутренних компонентов сборщиков мусора нелегко. (Хотя в случае GC Hotspot вы можете посмотреть исходный код...)

EDIT: в ответ на комментарий OP...

"Кажется, так, как я думал, - не обойти стороной" остановить мир ".

Это зависит. В случае Java 6 Concurrent Collector существует две паузы во время маркировки корней (включая стеки), а затем маркировка/копирование других объектов идет параллельно. Для других видов параллельного коллектора используются барьеры чтения или записи, когда сборщик работает для ловушки ситуаций, когда коллектор и прикладные потоки будут иным образом мешать друг другу. У меня сейчас нет моей копии [Джонса], но я также помню, что можно сделать "остановить мир" незначительным... за счет более дорогих операций с указателями и/или не собирать все мусора.

Ответ 2

Вы правы, что сборщик мусора должен приостановить все потоки приложений. Это время паузы может быть восстановлено с помощью JVM Sun, используя параллельный коллектор, который задерживает часть работы без остановки приложения, но stll должен приостанавливать потоки приложений.

См. здесь http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html#par_gc и здесь http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html#cms для получения подробной информации о том, как Sun JVM управляет сбором мусора в последних JVM.

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

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

Ближе всего вы можете найти концепцию сетевого распределителя памяти в J2EE - объединение пулов объектов/экземпляров, которое выполняется с помощью фреймворков и приложений. Например, в JBOSS есть пулы EJB и пулы подключения к базам данных. Однако эти объекты обычно объединяются из-за высокой стоимости создания, а не из-за сбоев сбора мусора.

Ответ 3

Я полагаю, что IBM провела некоторые исследования по улучшению производительности GC в многоядерных системах, которая включает в себя работу по сокращению или устранению проблемы "все останова".

например. видеть: Параллельный, инкрементальный и параллельный GC для серверов (pdf)

Или google что-то вроде "одновременной коллекции мусора ibm"

Ответ 4

AFAIK, когда GC делает свою вещь, VM блокирует все запущенные потоки - или, по крайней мере, когда он уплотняет кучу. Так ли это в современных реализациях CLR и JVM (производственные версии по состоянию на январь 2010 года)?

В Sun Sun Hotspot JVM и Microsoft CLR есть параллельные GC, которые останавливаются в мире только на коротких этапах (чтобы получить самосогласованный снимок глобальных корней, из которых доступны все доступные данные), а не для целых циклов сбора. Я не уверен в их реализации уплотнения, но это очень редкое явление.

Если это действительно так, как тяжелые корпоративные двигатели, такие как JBOSS и Glassfish, поддерживают стабильно высокий уровень TPS?

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

Ответ 5

Существует несколько алгоритмов GC, доступных с Java, не все из которых блокируют все запущенные потоки. Например, вы можете использовать -XX: + UseConcMarkSweepGC, который работает одновременно с приложением (для сбора поколенного поколения).

Ответ 6

Текущая современная сборка мусора для Java по-прежнему включает случайные паузы "остановить мир". G1 GC, представленный на Java 6u14, работает, хотя большая часть его работает одновременно, когда память действительно низкая, и ей нужно сжать кучу, тогда она должна обеспечить, чтобы никто не столкнулся с кучей под ней. Это требует, чтобы больше ничего не разрешалось. Чтобы узнать больше о G1 GC, просмотрите презентации от Sun.