From c7ba3e46291575b3cc896487e1e3437aab9c6f27 Mon Sep 17 00:00:00 2001 From: Dmitrii Krosh Date: Wed, 1 Jul 2026 19:19:09 +0300 Subject: [PATCH] add Docs sec --- Docs/TODO.md | 19 ++++++++ Docs/set:version.md | 92 ++++++++++++++++++++++++++++++++++++ Docs/set:version/raw_data.md | 46 ++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 Docs/TODO.md create mode 100644 Docs/set:version.md create mode 100644 Docs/set:version/raw_data.md diff --git a/Docs/TODO.md b/Docs/TODO.md new file mode 100644 index 0000000..c790ea8 --- /dev/null +++ b/Docs/TODO.md @@ -0,0 +1,19 @@ +# TODO + +just to-do for krosh. + +- [ ] Описать работу кода set.c + - [ ] Общий "скелет" + - [ ] часть вводов-выводов + - [ ] hash часть + - [ ] delta часть + - [ ] golomb часть + - [ ] base62(64) часть +- [ ] Протестировать, понять процент прироста от optimized кода +- [ ] research + - [ ] хэши, оптимальный ли этот, подходят ли другие + - точно были вопросы к коллизиям + кодировкам изначального ascii (условно много повторов на одинаковых наборах) + - [ ] кодировки, существование и применимость других + - [ ] реализация base62 +- [ ] Написать "аналог" на другом ЯП (Python?) + - решить, какие использовать хэш функции, функции кодирования и т.д. diff --git a/Docs/set:version.md b/Docs/set:version.md new file mode 100644 index 0000000..e14a143 --- /dev/null +++ b/Docs/set:version.md @@ -0,0 +1,92 @@ +# set:version + +what is happening inside [set:version](https://git.altlinux.org/gears/r/rpm.git?a=blob;f=lib/set.c) + +## Зачем + +set:version в alt-rpm позволяет сопоставлять Provides и Requires пакетов не обычным сравнением версий, а сравнением специальных set-строк зависимостей вида +```text +libfoo.so.X = set: +``` + +`encoded-set` формируется на основе символов, необходимых/предоставляемых пакетом. Данный механизм позволяет гарантировать (с точностью до коллизий хэша, об этом будет далее) наличие всех требуемых символов в библиотеке. Это исключает ситуации, при которых ">= версий" ломается при удалении символа из библиотеки, а также ситуаций совпадения SONAME библиотек с разным набором символов. + +set-строки (являющиеся перекодированным списком символов) генерируются способом, который позволяет их сравнивать между собой на предмет включения одного множества символов в другой. + +## Реализация `set.c` + +`set.c` предоставляет 5 "публичных" API для работы set:version + +```c +int rpmsetcmp(const char *set1, const char *set2); + +struct set *set_new(void); +void set_add(struct set *set, const char *sym); +const char *set_fini(struct set *set, int bpp); +struct set *set_free(struct set *set); +``` + +### `rpmsetcmp()` + +Основная функция, сравнивающая строки и выдающая результат в зависимости от включения: + +* 1: set1 > set2 +* 0: set1 == set2 +* -1: set1 < set2 (aka set1 \subset set2) +* -2: set1 != set2 +* -3: set1 decoder error +* -4: set2 decoder error + +на основе [данной](https://github.com/svpv/rpmss/blob/4256d86cc9ba1aa4ceb8c0f03f7d48675d9d27bb/set.h#L12) заметки, `set1` лучше делать как `Provides` для лучшей производительности. + +### `set_new()` + +Создаёт пустой объект `struct set`. + +Внутри `struct set` — это временный контейнер для строк символов и их будущих hash-значений. +Из релизации: +> internally struct set is just a bag of strings and their hash values. + +### `set_add()` + +Добавляет строковый символ в set. + +Использование: +```c +set_add(s, "printf@@GLIBC_2.2.5"); +set_add(s, "malloc@@GLIBC_2.2.5"); +``` + +### `set_fini()` + +Финализирует множество и возвращает готовую set-version строку. + +Внутри происходит основная работа: +1. Jenkins hash +2. обрезка до bpp бит +3. сортировка +4. delta кодирование +5. golomb кодирование +6. base62(64) кодирование + +### `set_free()` + +Освобождает struct set и его внутренние строки. + +## `set.c` под капотом + +### hash + +### delta + +### golomb + +### base62 + +## Комментарии + +## additional + +[коды](https://altlinux.space/arseny/atsv-research) от Арсения для наглядности происходящего + +some funny [msg's](https://lists.pld-linux.org/mailman/pipermail/pld-devel-en/2013-November/012467.html) diff --git a/Docs/set:version/raw_data.md b/Docs/set:version/raw_data.md new file mode 100644 index 0000000..7da1213 --- /dev/null +++ b/Docs/set:version/raw_data.md @@ -0,0 +1,46 @@ +# raw_data + +## messages from tg + +[6/23/26 9:57 PM] Arseny: Кстати. У меня есть серьёзная математическая, она же очень серьёзная алгоритмическая задача на исследование. ALT set:version (https://git.altlinux.org/gears/r/rpm.git?a=blob;f=lib/set.c) нужен майнтейнер. +[6/23/26 9:57 PM] Arseny: Вы хотели алгоритмов? Вот, расскажите мне про этот. +[6/23/26 9:57 PM] Arseny: весь алгоритм можно разбить на 4 последовательных стадии. + +0) Задача в том, чтобы проверять, выполняется ли R ⊂ P. +множества, стоящие в позиции P, даются командой навроде nm --dynamic -j -U /usr/lib64/libyourfavourite.so.N. +множества, стоящие в позиции R, даются командой навроде nm --dynamic -j -u /usr/bin/yourfavouriteprog, или там может быть иной .so. +Тут, наверное, ещё и введение в предметную область должно быть. + +1) hash: N элементов сбрасываются в этот самый хеш; его эффективность бы стоило оценить хорошенько. (гипотеза от меня: он вообще-то плохой и даёт много коллизий на интересных нам инпутах), в результате K <= N отсортированных хешей, чисел из [0; 2**10) (по умолчанию 10 бит на хеш); +2) delta: K <= N чисел из прошлого шага заменяются на разности с предыдущими, и получаются по-другому распределённые числа, чаще маленькие и очень, очень мало сверхбольших; есть мнение, что они для равномерно распределённых хешей распределены геометрически; +3) golomb: эти K разностей кодируются по Rice-Golomb (https://en.wikipedia.org/wiki/Golomb_coding), делитель по умолчанию 2**7; получается префиксный код из K битострок, которые можно слева направо прочесть без lookahead и восстановить массив разностей; +4) (якобы) base62: их конкатенация кодируется в буквы. + +(2) и (3) близки к очевидно-понятным; я поизучал, реализовал на питоне (https://altlinux.space/arseny/atsv-research) и снова поизучал. +А вот (1) и (4) я не занимался совсем. +От (4) у меня тоже башка взрывается, а (1) можно очень хорошо так поизучать, и существует, наверное, обширная литература. +[6/23/26 9:57 PM] Arseny: grep -A16 Jenkins lib/set.c +вот в этом дереве исходников (https://git.altlinux.org/gears/r/rpm.git?p=rpm.git;a=blob;f=lib/set.c;h=9474a2ee6d7c;hb=a01a87db6e8a) +[6/23/26 9:57 PM] Arseny: Пусть параметр-делитель равен M, и энкодеру на вход поступает число A. Тогда ищутся такие q и r < q, что A = qM + r. Частное кодируется унарной кодировкой из единиц, за ним следует нулик, а далее ровно log₂M бит на остаток. Подобрать M нужно с умом. +```sh +python3 stringset.py 10 7 <