diff --git a/articles/for-alt/article.md b/articles/for-alt/article.md new file mode 100644 index 0000000..3fde57b --- /dev/null +++ b/articles/for-alt/article.md @@ -0,0 +1,90 @@ +# Исследование и улучшение механизма работы `set`-строк в ALT RPM + +Ориентир на 700 слов, 9к символов +(!!!)/(???) - дополнить/уточнить +всё ещё куда-то надо включить "хэш клёвый, но медленный, вот тесты" + +## 1. Зачем нужны set-строки + +Обычная зависимость от версии библиотеки не гарантирует, что в ней остались все нужные программе символы: символ можно удалить, не сменив SONAME, а одинаковые SONAME могут скрывать разные наборы экспортов. Поэтому ALT RPM использует версии зависимостей вида `set:`. Для `Provides` такая строка описывает символы, предоставляемые библиотекой, а для `Requires` - символы, которые конкретный потребитель требует от неё. В такой конфигурации сравниваются не номера версий, а включение множеств: все хэши символов из `Requires` должны присутствовать в `Provides`. +Гарантия вероятностная, поскольку вместо полноценных имён символов хранятся усечённые хэши, но ответ "символ отсутствует", когда он есть мы не получим + +## 2. Структура set-строки + +set-строка формируется следующим образом: + +1. Список символов формируется автодепами `rpm-build`. +2. По количеству `Provides` символов вычисляется `bpp` (количество бит до которых обрезается хэш символа при формировании строки). (!!!) +3. Для каждого символа считается хэш-функция (используется Jenkins OAAT), хэш обрезается до `bpp` бит. +4. Массив хэшей сортируются, повторы удаляются. +5. Абсолютные значения заменяются дельтами между значениями +6. Для кодировки Golomb-Rice вычисляется параметр `Mshift`. (!!!) bpp - log2i(cnt) - 1 +7. Массив дельт сжимаются кодировкой Golomb-Rice. +8. Битовый поток преобразуется в Base62-строку. + +Примечание: при формировании set-строки для `req` символов, `bpp` вычисляется по количеству `prov` символов в актуальной (???) версии библиотеки для избежания сильного усечения хэшей при небольшом количестве требуемых символов. + +Итоговая строка выглядит следующим образом: + +```text +set: +``` + +```text +bpp_char = bpp - 7 + 'a' +Mshift_char = Mshift - 7 + 'a' +``` + +Краткая схема: + +``` +массив строк + | (Jenkins OAAT) + v +массив усечённых хэшей + | (qsort) + v +отсортированный массив хэшей + | (вычисление разницы между элементами) + v +массив delta + | (Rice-Golomb преобразование) + v +битовый массив + | (base62 преобразование) + v +set-строка +``` + +### Механизм сравнения set-строк + +Для проверки включения множества символов `req` в множество `prov` необходимо выполнить обратное декодирование следующим образом: + +``` +set-строка + | (обратное base62 преобразование) + v +битовый массив + | (обратное Rice-Golomb преобразование) + v +массив delta + | (вычисление изначальных значений) + v +массив усечённых хэшей (отсортированный) +``` + +Значения хэшей в массивах приводятся к минимальному `bpp` из двух set-строк (сохраняется отсортированность и дистинктивность(???)). + +После получения отсортированных массивов хэшей из set-строк, включение символов (а точнее их усечённых хэш-значений) одного множества во второе проверить не составляет труда. + +## 3. Практическая реализация + +Несмотря на описанную структуру set-строки, на практике в текущем `lib/set.c` применяется множество оптимизаций и улучшений, направленных на ускорение работы `rpmsetcmp(const char *set1, const char *set2)` (функции, выдающей результат включения множеств). Рассмотрим основные из них. + +### 3.1. Слитый декодер + +### 3.2. Кэширование `Provides` set-строк + +### 3.3. Быстрое сравнение включения множеств символов + +## 4. Дальнейшие оптимизации