docs/notes/garbage-collection

This commit is contained in:
Dmitry Zuikov 2023-10-16 09:34:14 +03:00
parent 9f745148e6
commit 87092bd64f
1 changed files with 116 additions and 0 deletions

View File

@ -0,0 +1,116 @@
Немного про сборку мусора в HBS2
Предпосылки:
- В блоках / содержимом транзакций может быть всё, что
угодно. Например, ссылки. Нет возможности заставить
разработчиков не делать ссылки изнутри бинарных блоков,
так же как и нет возможности надёжно отслеживать наличие
рукояток для сборщика мусора для структур данных.
Ведь приложения могут быть сторонними, в том числе
такими, которые вообще не пользуются Haskell и
библиотеками hbs2.
Простой пример: текстовый документ, который содержит
ссылки в текстовом виде.
Из этого получается, что мы не можем полагаться на наше
представление об устройстве блоков, и должны переложить это
на пользователя.
Каким образом:
Первая мысль: сделать некие pinned refs, в каждой такой
ссылке - дерево хэшей блоков, и эти блоки не трогать при
сборке, если есть pinned ref.
При сборке мусора использовать только их.
Все, что не pinned --- будет собираться.
Минус подхода: как быть с хостами, на которых нет pinned
ref?
Если pinned ref делать локальными. Если их не делать
локальными, то нужен протокол, который крайне похож на
refchan/reflog.
Выглядит не очень.
Другой подход: мы действуем в рамках имеющихся ссылок,
ссылки парсим, контент распознаём при помощи tryDetect.
Количество подобных структур стараемся не увеличивать.
Pinned refs для надёжности можно сделать тоже.
Далее.
Может ли сборщик быть инкрементальным?
Или даже так: может ли он быть НЕ инкрементальным?
Ссылки обновляются всё время, мы не можем "остановить мир"
без угрозы потери консистентности.
Поэтому, как бы поступить?
допустим, началась сборка.
storage/refs не трогаем, пускай пишут ссылки.
storage/blocks делаем файлом.
в нём - ссылка на "текущий" каталог блоков.
Когда пошёл процесс GC, создаём новый пустой каталог
blocks-N, где <<N>> - номер <<поколения>>.
устанавливаем sorage/blocks на blocks-N.
Новые блоки начинают писаться в него.
При чтении делаем две вещи:
1. инкрементируем "refcount" для каждого блока
2. если через какое-то время T refcount для блока /= 0,
то переносим его в новое поколение.
3. если спустя TBD - refcounf == 0, то блок
можно удалить?
мутноватая тема. спустя какое время?
Ок, другой вариант. Делаем клон сторейджа полностью, со
ссылками. собираем мусов в нём, относительно тех ссылок,
которые в нём зафиксированы.
В процессе работы с новым сторейджем действительно выполняем
копирование из "старого" поколения в новое, если блок
оказался востребованным в новом поколении.
<<Старая>> копия сторейджа иммутабельна, в смысле новые
ссылки и блоки не создаются.
Когда закончили сборку, то просто добавляем все выжившие
блоки обратно в новое поколение, а временный каталог для
сборки прибиваем.
Развитие идеи в том, что мы не делаем копий блоков, а
оперируем только ссылками. тогда, допустим, в начале цикла
сборки мы устанавливаем всем блокам refcount=0, делаем
снапшот ссылок, сканируем ссылки из этого снапшота и ищем
выжившие блоки, потом удаляем те, которые не выжили.
В процессе удаления хорошо бы понять, что новых ссылок не
появилось и они не указывают на блоки, которых у нас нет, а
так же хорошо бы не удалять блоки в процессе обновления
ссылки.
TO BE CONTINUED...