sicp.io
5.3.2 · Поддержание иллюзии бесконечной памяти

Копирующая сборка мусора с указателями пересылки

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

Вопрос для размышления

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

  • Различение from-space и изначально пустого to-space
  • Копирование только указателей на пары, достижимых из переданных корней root
  • Установка записи forwarding перед рекурсивным копированием полей
  • Повторное использование одного нового указателя для каждой повторной ссылки на старую ячейку
  • Сохранение цикла через распознавание указателя forwarding
  • Измерение освобожденных ячеек и продвижения указателя free

copy-value возвращает атомы без изменений. Для указателя на пару процедура сначала проверяет запись forwarding по старому индексу. При отсутствии записи выделяется одна ячейка placeholder в to-space и записывается новый указатель еще до перехода по любому из полей. Затем car и cdr рекурсивно копируются в эту ячейку placeholder. Запись нового указателя в первую очередь делает конечной обработку как разделяемых данных, так и циклов.

В первой куче выделено пять ячеек, но только три из них достижимы из двух корней root. Скопированные ячейки left и right указывают на один скопированный разделяемый хвост shared, тогда как обе ячейки мусора сохраняют ложные записи forwarding. Вторая куча содержит цикл на себя, поэтому копирование cdr снова встречает старый указатель и сразу повторно использует уже установленный новый указатель. Эта конечная программа выполняет один явный сбор мусора в пределах фиксированной емкости semispace.

Код SICP4,742 из 1,048,576 байт UTF-8
Примеры
Результат
Вывод
Значение
Диагностика
Трасса выполнения0 / 0 событий
    Запуски происходят внутри браузера с отображением результата программы и трассы выполнения.
    Ожидаемый результат

    Сборка мусора для графа с разделением возвращает (5 3 2 (a shared) (b shared) #t #f #f). Сборка циклического графа возвращает (1 node #t #f).

    На что обратить внимание в трассе

    В графе с разделением проследите переход первого старого указателя shared в новое выделение памяти, а второго вхождения в существующую запись forwarding. Убедитесь, что старые индексы 3 и 4 никогда не посещаются. В цикле найдите запись forwarding до того, как рекурсивное копирование cdr снова достигнет старого узла.

    Попробуйте сами

    Измените программу и сравните результат.

    Добавьте третий корень root, указывающий прямо на разделяемый хвост shared, затем измените скопированный хвост. Спрогнозируйте новое количество выделенных ячеек и каждое наблюдение через root. Затем поменяйте местами semispace и выделите еще одну ячейку.

    Показать подсказку

    Дополнительный корень root к уже пересланному объекту не добавляет скопированных ячеек. После сборки мусора все клиенты должны использовать перезаписанные корни root в to-space, а не устаревшие указатели из from-space.

    Завершить этот урок

    В этой главе пройдено 0 из 23 урока0%