# Исследование и улучшение механизма работы `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. Дальнейшие оптимизации