Возможные подводные камни этого асинхронного сборщика мусора - PullRequest
2 голосов
/ 16 апреля 2011

Я немного изучил сборку мусора, в основном относящуюся к серверным приложениям / приложениям реального времени, и начал набирать алгоритм, с помощью которого можно было бы создать асинхронную систему сбора мусора. Поскольку я сейчас начинаю эту тему, поэтому я не очень хорошо знаю алгоритмы gc, мне было интересно узнать о возможных подводных камнях такой реализации. Алгоритм очень сырой, и со многими неопределенными частями.

Вот как я об этом подумал:

  • каждый поток имеет свое собственное пространство кучи для управления и хранит список принадлежащих ему указателей, которые используются другими потоками При этом сборка мусора работает полностью асинхронно с запущенными потоками и:
  • Фаза 1 начинается с корней нитей и маркирует все объекты, которые они могут восстановить. Если мы попадаем в пространство другого потока, мы перестаем следовать этому указателю и помечаем этот указатель как «используемый» в потоке владельца
  • после того, как мы отметили все регионы, мы выбираем регион (возможно, с наибольшим количеством мертвых ссылок, насколько это возможно) и начинаем копировать ссылки на его живой объект в другое пространство. (это может быть целое пространство кучи потока, но я думаю, что эта операция может потребовать слишком много памяти)
  • копирование начинается с установки с помощью CAS флага, который указывает, что объект копируется. Любое изменяемое действие, которое будет выполнено с этим конкретным объектом, пока установлен этот флаг, будет блокировать вращение до тех пор, пока потоком gc не будет установлен новый адрес. Когда копирование заканчивается, новый адрес устанавливается на старый, и любая изменяемая ссылка, которая будет выполнена на объекте, будет перенаправлена ​​на новый объект
  • после обновления всех ссылок, сделанных на эти указатели с использованием CAS, старое пространство, наконец, освобождается (новые указатели не будут обновляться с неправильным адресом, поскольку каждый мутатор сначала проверяет, изменилась ли ссылка на места)

Вот и все!

В любом случае, я весьма взволнован возможной реализацией, которая не останавливает мир, и использует только быстрые спин-блокировки, которые применяются только к копируемому объекту. Но я хотел бы знать, возможно ли это реализовать, или есть ли возможность где-нибудь повесить указатель, или утечки памяти, или это неэффективно, и т. Д. Любая информация, которая будет способствовать этому, будет принята с благодарностью!

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

Спасибо!

---- РЕДАКТИРОВАТЬ: Благодаря вкладу Эрнеста я думаю не об использовании алгоритма копирования, а, возможно, о простой пометке. Это потому, что нам нужно каждый раз проверять доступ к переменной объекта, если указатель обновлен. Это кажется мне довольно большими накладными расходами. Не так ли?

Ответы [ 3 ]

1 голос
/ 16 апреля 2011

Только что видел это недавно http://java -monitor.com / forum / showthread.php? T = 890

Насколько я понимаю, вы говорите о модели, аналогичной той, чтоиспользуется Erlang VM - каждый поток имеет свою кучу.Это возможно по характеру Эрланга - не требуются спин-блокировки (по крайней мере, для кучи потоков).

1 голос
/ 19 июня 2012

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

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

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

Фаза 1 начинается с корней потоков и помечает все объекты, которые они могут восстановить.Если мы попадаем в пространство другого потока, мы перестаем следовать этому указателю и помечаем этот указатель как «используемый» в потоке владельца

Если это делается одновременно с работающим мутатором, как вы можете предотвратить это?условия гонки, когда мутаторы изменяют топологию, чтобы ввести или исключить ссылки между кучами, пока GC выполняет эту маркировку?

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

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

копирование начинается с установки с помощью CAS флага, который указывает, что объект копируется.Любое изменяемое действие, которое будет выполнено с этим конкретным объектом, пока установлен этот флаг, будет блокировать вращение до тех пор, пока потоком gc не будет установлен новый адрес.Когда копирование заканчивается, новый адрес устанавливается на старый, и любая изменяемая ссылка, которая будет выполнена на объекте, будет перенаправлена ​​на новый объект

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

Спин-блокировки также вредны дляпараллелизм, потому что вы не только связываете поток, но и сжигаете ядро, которое больше не может выполнять работу, которую вы ожидаете!Смотрите ошибку последнее замедление ядра в GHC.Решение без ожидания будет использовать CAS, чтобы поток мутатора помогал с работой GC, а не блокировать ожидание выполнения другим потоком.

после обновления всех ссылок на эти указатели, использующие CAS,старое пространство, наконец, освобождается (новые указатели не будут обновляться с неправильным адресом, так как каждый мутатор сначала проверит, изменилась ли ссылка на места)

Ok.

1 голос
/ 16 апреля 2011

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

...