5.6 KiB
Исследование и улучшение механизма работы set-строк в ALT RPM
Ориентир на 700 слов, 9к символов (!!!)/(???) - дополнить/уточнить всё ещё куда-то надо включить "хэш клёвый, но медленный, вот тесты"
1. Зачем нужны set-строки
Обычная зависимость от версии библиотеки не гарантирует, что в ней остались все нужные программе символы: символ можно удалить, не сменив SONAME, а одинаковые SONAME могут скрывать разные наборы экспортов. Поэтому ALT RPM использует версии зависимостей вида set:<encoded-set>. Для Provides такая строка описывает символы, предоставляемые библиотекой, а для Requires - символы, которые конкретный потребитель требует от неё. В такой конфигурации сравниваются не номера версий, а включение множеств: все хэши символов из Requires должны присутствовать в Provides.
Гарантия вероятностная, поскольку вместо полноценных имён символов хранятся усечённые хэши, но ответ "символ отсутствует", когда он есть мы не получим
2. Структура set-строки
set-строка формируется следующим образом:
- Список символов формируется автодепами
rpm-build. - По количеству
Providesсимволов вычисляетсяbpp(количество бит до которых обрезается хэш символа при формировании строки). (!!!) - Для каждого символа считается хэш-функция (используется Jenkins OAAT), хэш обрезается до
bppбит. - Массив хэшей сортируются, повторы удаляются.
- Абсолютные значения заменяются дельтами между значениями
- Для кодировки Golomb-Rice вычисляется параметр
Mshift. (!!!) bpp - log2i(cnt) - 1 - Массив дельт сжимаются кодировкой Golomb-Rice.
- Битовый поток преобразуется в Base62-строку.
Примечание: при формировании set-строки для req символов, bpp вычисляется по количеству prov символов в актуальной (???) версии библиотеки для избежания сильного усечения хэшей при небольшом количестве требуемых символов.
Итоговая строка выглядит следующим образом:
set:<bpp_char><Mshift_char><base62 строка>
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) (функции, выдающей результат включения множеств). Рассмотрим основные из них.