WIP plan.md for asvk

This commit is contained in:
2026-08-11 03:58:29 +03:00
parent a5e583f600
commit 53332b0f62
+173
View File
@@ -0,0 +1,173 @@
# Исследование алгоритма разрешения зависимостей в 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),
$$
Полная сложность алгоритма холодного сравнения:
...
При попадании в кэш:
...