Files
ARSV/articles/for-asvk/plan.md
T
2026-08-11 03:58:29 +03:00

174 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Исследование алгоритма разрешения зависимостей в ALT RPM
## Замысел и структура статьи
Статья будет как решение одной формальной задачи. В ALT RPM пакет-потребитель задаёт множество
требуемых символов $R$ (`Requires`), а пакет-поставщик - множество предоставляемых
символов $P$ (`Provides`). Зависимость выполнима тогда и только тогда, когда
$$
R \subseteq P.
$$
Явное перечисление тысяч ELF-, Python- и файловых символов раздувает RPM-метаданные,
поэтому множества представлены компактными set-строками.
## 1. Постановка задачи и данные ALT Linux
Ввести обозначения для bpp(b), множеств, хэш функций(H), длин строк и т.д.
Проверяемое программой условие имеет вид
$$
H_b(R)\subseteq H_b(P).
$$
Отмечаем вероятностную природу: из $R\subseteq P$ следует
$H_b(R)\subseteq H_b(P)$, поэтому коллизия не создаёт ложного отказа. Обратное
неверно: отсутствующий символ может совпасть по хешу с символом из $P$ и дать
ложное принятие зависимости.
(Представить данные ниже табличкой)
Привести срез Sisyphus `x86_64 + noarch`: 47 367 пакетов, 14 761 `Provides`-отношение и 68 857
`Requires`-отношений. Для 68 198 реально сопоставимых пар медианы равны
$p=480$, $r=13$, $p/r=28.1$; p75 - 1886, 37 и 80; p90 - 6219, 104 и 257.
В 92.4% пар выполняется $p/r\ge 4$. Это к теме, почему рассматриваем разреженные множества.
## 2. Устройство существующей `set:`-строки
Даём схему формата:
```
массив строк
| (Jenkins OAAT)
v
массив хэшей
| (qsort)
v
отсортированный массив хэшей
| (вычисление разницы между элементами)
v
массив delta
| (Rice-Golomb преобразование)
v
битовый массив
| (base62 преобразование)
v
set-строка
```
Нужно отдельно разобрать заголовок, диапазоны `bpp` и `Mshift`, внешний префикс
`set:` и роль Base62: строка должна оставаться допустимым токеном версии RPM.
Полезна небольшая иллюстрация на 5-8 символах: исходные имена, хеши,
отсортированный массив, дельты, биты кода и итоговая строка.
Но. Это много альт-специфики, может настолько глубоко не стоит (хотя и не очень глубоко)
### 2.1. Хеширование и вероятность коллизий
! Всё ещё нет нормального анализа коллизий
Текущий код использует 32-битный Jenkins OAAT и оставляет $b$ бит. Для модели
равномерного независимого хеширования ожидаемое число столкнувшихся пар среди
$n$ различных символов равно
(будет мудрёная формула, теория)
В статье формулы дополняем разными табличками по реальным данным из Sisyphus: распределения $p,r,b$, ожидаемые коллизии, реальные.
(Другие хэши идут далее)
### 2.2. Кодирование Golomb-Rice
Для отсортированных значений $0\le x_1<\dots<x_n<N$ определить
$\delta_1=x_1$, $\delta_i=x_i-x_{i-1}$.
Занимаеи столько и столько бит. В реализации параметр выбирается из
$b$ и $n$ приблизительно как
$$
m=b-\lfloor\log_2 n\rfloor-1
$$
с ограничением допустимым диапазоном формата. При средней дельте
$\mathbb E\delta\approx 2^b/n$ это даёт ожидаемую длину порядка
...
### 2.3. Base62
Пояснить экзотичность Base62, его алфавит, принцип кодирования, Z-escape,
## 3. Построение `set:`-строк в `set.c`
(фактически его можно в 2 упихать)
Рассказать путь `set_new()` - `set_add()` - `set_fini()` и отдельно объяснить
сложные участки:
(а тут и нет сложного, всё в cmp запихали)
Можно рассказать о слитом энкодере, но это есть в переписанной части
В оригинальном варианте используется `qsort()`
Записать итоговую сложность построения:
...
И доп памяти:
...
## 4. Сравнение `set:`-строк
### 4.1. Обратное декодирование
Кратко пройти обратную цепочку:
```
set-строка
| (обратное base62 преобразование)
v
битовый массив
| (обратное Rice-Golomb преобразование)
v
массив delta
| (вычисление изначальных значений)
v
массив хэшей
```
Если `bpp` различается, более точное множество проецируется на меньшее число бит,
после чего снова удаляются дубликаты. (btw, тут есть сортировка слиянием, интересный момент)
### 4.2. Кэш декодированных множеств
В исходном `set.c` кэш содержит 256 записей (`CACHE_SIZE=256`), при вытеснении
использует позицию 243 (`PIVOT_SIZE=243`), `free()` и два `memmove()`. Ключ включает
короткий fingerprint, а окончательная проверка требует сравнения строки.
- что именно кэшируется;
- стоимость линейного поиска, `strcmp`, перемещений и аллокаций;
- слабое повторное использование при потоке десятков тысяч различных пар;
(всё надо сильно короче расписывать)
### 4.3. Проверка включения и «прыжок» по массивам
После декодирования задача сводится к двум возрастающим массивам. Базовый вариант
рассказ про IFLT4 и IFLT8
Худшая асимптотика остаётся
$$
T_{\subseteq}(p,r)=O(p+r),
$$
Полная сложность алгоритма холодного сравнения:
...
При попадании в кэш:
...