Сжатие реализации сборщика мусора в C ++ 0x - PullRequest
24 голосов
/ 30 декабря 2010

Я внедряю компактный сборщик мусора для личного использования в C ++ 0x, и у меня возник вопрос.Очевидно, что механика коллектора зависит от движущихся объектов, и мне было интересно, как реализовать это с точки зрения типов интеллектуальных указателей, которые на него указывают.Я думал либо о указателе на указатель в самом типе указателя, либо о том, что сборщик поддерживает список указателей, которые указывают на каждый объект, чтобы их можно было модифицировать, устраняя необходимость в двойной де-реф при доступеуказатель, но добавляет дополнительные издержки во время сбора и дополнительные накладные расходы памяти.Какой лучший способ пойти сюда?

Редактировать: Моя главная задача - быстрое распределение и доступ.Я не занимаюсь особо эффективными коллекциями или другим обслуживанием, потому что это не совсем то, для чего предназначен GC.

Ответы [ 3 ]

11 голосов
/ 17 января 2011

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

На самом деле я написал gc на C ++, который работает с существующим кодом C ++, и у него былокомпактор на одном этапе (хотя я уронил его, потому что он был слишком медленным).Но есть много неприятных семантических проблем.Я упомянул Бьярне всего несколько недель назад, что в C ++ нет оператора, необходимого для его правильного выполнения, и ситуация такова, что он вряд ли когда-либо будет существовать, поскольку имеет ограниченную полезность.переадресовать меня ".Что происходит, так это то, что вы на самом деле не перемещаете объекты.Вы просто используете mmap для изменения адреса объекта.Это намного быстрее, и, по сути, он использует функции виртуальной машины для предоставления дескрипторов.

Без этой возможности вам потребуется способ выполнения перекрывающегося перемещения объекта,что вы не можете сделать в C ++ эффективно: сначала вам придется перейти на временное.В C это намного проще, вы можете использовать memmove.На каком-то этапе все указатели на или на перемещенные объекты должны быть скорректированы.

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

Так что не беспокойтесь о ручках, они не работают.

Это то, что яделал в Феликсе: звоните new(shape, collector) T(args).Здесь shape является дескриптором типа, включая список смещений, которые содержат (GC) указатели, и адрес подпрограммы для завершения объекта (по умолчанию он вызывает деструктор).

Он также содержит флаг, сообщающий, можно ли переместить объект с помощью memmove.Если объект большой или неподвижный, он выделяется на malloc.Если объект небольшой и подвижный, он размещается на арене при условии наличия места на арене.

Арена уплотняется путем перемещения всех объектов на ней и использования информации о форме для глобальной корректировки всехуказатели на или на эти объекты.Сжатие может выполняться постепенно.

Недостатком для программиста C ++ является необходимость создания правильного shape объекта для передачи.Это не беспокоит меня, потому что я реализую язык, который может генерировать информацию о форме автоматически.

Теперь: ключевой момент: чтобы сделать сжатие, вы должны использовать точный коллектор,Уплотнение не может работать с консервативным сборщиком.Это очень важно.Можно допустить некоторую утечку, если вы видите значение, которое выглядит как указатель, но оказывается целым числом: некоторый объект не будет собран, но обычно это не так уж и сложно.Но для уплотнения вам нужно настроить указатели, но лучше не менять это целое число: так что вы должны знать наверняка , когда что-то является указателем, поэтому ваш коллектор должен бытьточный: форма должна быть известна.

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

1 голос
/ 02 января 2011

Это довольно простой вопрос, поэтому вот прямой ответ:

Mark-and-sweep (а иногда mark-and-compact, чтобы избежать фрагментации кучи) - самый быстрый, когда речь идет о распределении и доступе (избегая двойных de-refs).Это также очень легко реализовать.Поскольку вас не беспокоит влияние на производительность коллекции (метка-и-развертка имеет тенденцию замораживать процесс недетерминированным образом), это должен быть путь.1008 *

http://www.brpreiss.com/books/opus5/html/page424.html#secgarbagemarksweep http://www.brpreiss.com/books/opus5/html/page428.html
0 голосов
/ 30 января 2013

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

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

...