article for asvk
This commit is contained in:
@@ -0,0 +1,119 @@
|
|||||||
|
\Title{Гудов Д.О.}{Исследование алгоритма разрешения зависимостей в ALT RPM}
|
||||||
|
|
||||||
|
\section*{Введение}
|
||||||
|
|
||||||
|
Одной из задач пакетного менеджера является проверка совместимости устанавливаемого программного обеспечения с уже имеющимися или одновременно устанавливаемыми библиотеками. Традиционная зависимость от имени библиотеки и номера её версии не всегда достаточна: отдельный экспортируемый символ может быть удалён без изменения SONAME, а библиотеки с одинаковым SONAME могут предоставлять различные программные интерфейсы. В результате формально удовлетворённая зависимость от версии ещё не гарантирует, что динамический загрузчик найдёт все символы, необходимые программе.
|
||||||
|
|
||||||
|
В ALT RPM эта задача решается при помощи специальных версий зависимостей вида \texttt{set:<encoded-set>} [\Ref{SETC}]. Для отношения \texttt{Provides} такая строка описывает множество символов, экспортируемых библиотекой, а для отношения \texttt{Requires} --- символы, требуемые программой от конкретной библиотеки. При проверке зависимости обычное сравнение версий заменяется проверкой включения множеств. Полные имена символов при этом не сохраняются: они заменяются усечёнными хеш-значениями, сортируются и кодируются в компактную строку, допустимую как версия RPM.
|
||||||
|
|
||||||
|
Цель настоящей работы --- исследовать алгоритм построения и сравнения \texttt{set:}-строк, оценить вероятностные свойства хэша и вычислительную сложность алгоритма, а также определить направления оптимизации реализации.
|
||||||
|
|
||||||
|
%% В первых разделах формализуется решаемая задача, рассматриваются реальные данные репозитория Sisyphus, формат строки и путь её построения в исходной реализации \texttt{lib/set.c}.
|
||||||
|
|
||||||
|
\section{Постановка задачи и данные ALT Linux}
|
||||||
|
\label{PROBLEM}
|
||||||
|
|
||||||
|
Пусть $P$ --- множество символов, предоставляемых библиотекой, а $R$ --- множество символов, требуемых от неё программой. Обозначим $p=|P|$ и $r=|R|$. Зависимость выполнима тогда и только тогда, когда
|
||||||
|
\[
|
||||||
|
R\subseteq P.
|
||||||
|
\]
|
||||||
|
|
||||||
|
Списки символов формируются механизмом автоматического определения зависимостей \texttt{rpm-build}. Для \texttt{Provides} из динамической таблицы библиотеки выбираются доступные извне определённые символы. Для \texttt{Requires} утилита \texttt{ldd --bindings} устанавливает соответствие между требуемым символом и конкретной библиотекой-поставщиком; слабые неопределённые символы исключаются. Таким образом, одна строка \texttt{Requires} содержит только множество, связанное с данным поставщиком.
|
||||||
|
|
||||||
|
Явное хранение имён увеличивало бы RPM-метаданные пропорционально их суммарной длине. Поэтому используется усечённая хеш-функция c целым $b$, называемого в реализации \texttt{bpp},
|
||||||
|
\[
|
||||||
|
h_b(x)=h_{32}(x)\bmod 2^b,
|
||||||
|
\qquad
|
||||||
|
H_b(S)=\{h_b(x)\mid x\in S\},
|
||||||
|
\]
|
||||||
|
где $h_{32}$ --- 32-битная функция Jenkins one-at-a-time. Фактически \texttt{lib/set.c} проверяет условие
|
||||||
|
\[
|
||||||
|
H_b(R)\subseteq H_b(P).
|
||||||
|
\]
|
||||||
|
|
||||||
|
Такое представление сохраняет включение: из $R\subseteq P$ следует $H_b(R)\subseteq H_b(P)$. Следовательно, коллизия хешей не создаёт ложного отказа для корректной зависимости. Обратное утверждение неверно: отсутствующий символ из $R\setminus P$ может получить то же усечённое значение, что и один из символов $P$, и привести к ложному принятию зависимости. Тем самым предоставляемая гарантия имеет вероятностный характер.
|
||||||
|
|
||||||
|
Для оценки реальной нагрузки был исследован срез репозитория Sisyphus для архитектур \texttt{x86\_64} и \texttt{noarch}. Объём рассмотренных метаданных на момент 2026-08-20 приведён в табл.~\Ref{CORPUS}.
|
||||||
|
|
||||||
|
\begin{table}[H]
|
||||||
|
\begin{center}
|
||||||
|
\caption{\label{CORPUS}Объём исследованного среза Sisyphus}
|
||||||
|
\small
|
||||||
|
\begin{tabular}{|l|r|}
|
||||||
|
\hline
|
||||||
|
Объект & Количество \\
|
||||||
|
\hline
|
||||||
|
Пакеты & 47\,654 \\
|
||||||
|
\hline
|
||||||
|
Отношения \texttt{Provides} с \texttt{set:}-версией & 14\,859 \\
|
||||||
|
\hline
|
||||||
|
Отношения \texttt{Requires} с \texttt{set:}-версией & 69\,153 \\
|
||||||
|
\hline
|
||||||
|
Сопоставленные пары $P,R$ & 68\,492 \\
|
||||||
|
\hline
|
||||||
|
\end{tabular}
|
||||||
|
\end{center}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
661 отношений удовлетворены обычным неверсионированным \texttt{Provides}.
|
||||||
|
|
||||||
|
Для каждой сопоставленной пары декодировались мощности множеств $p$ и $r$, а также вычислялось индивидуальное отношение $p/r$. Квантили этих величин показаны в табл.~\Ref{CARDINALITIES}. Квантили отношения вычислялись непосредственно по парам.
|
||||||
|
|
||||||
|
\begin{table}[H]
|
||||||
|
\begin{center}
|
||||||
|
\caption{\label{CARDINALITIES}Мощности множеств в парах \texttt{Provides}/\texttt{Requires}}
|
||||||
|
\small
|
||||||
|
\begin{tabular}{|c|r|r|r|}
|
||||||
|
\hline
|
||||||
|
Квантиль & $p$ & $r$ & $p/r$ \\
|
||||||
|
\hline
|
||||||
|
0,50 & 480 & 13 & 28,1 \\
|
||||||
|
\hline
|
||||||
|
0,75 & 1\,886 & 37 & 80 \\
|
||||||
|
\hline
|
||||||
|
0,90 & 6\,219 & 104 & 257 \\
|
||||||
|
\hline
|
||||||
|
\end{tabular}
|
||||||
|
\end{center}
|
||||||
|
\end{table}
|
||||||
|
|
||||||
|
В 92,4\% сопоставленных пар выполняется $p/r\geq 4$. Следовательно, типичный проверяемый набор требований существенно разрежен относительно множества предоставляемых символов. Это наблюдение важно для алгоритма сравнения: последовательный симметричный просмотр двух массивов не всегда использует характерное различие их мощностей.
|
||||||
|
|
||||||
|
\section{Устройство существующей \texttt{set:}-строки}
|
||||||
|
\label{FORMAT}
|
||||||
|
|
||||||
|
Построение \texttt{set:}-строки выполняется как последовательность преобразований
|
||||||
|
\[
|
||||||
|
\begin{aligned}
|
||||||
|
\text{имена символов}
|
||||||
|
&\longrightarrow \text{усечённые хеши}
|
||||||
|
\longrightarrow \text{сортировка},\\
|
||||||
|
&\longrightarrow \text{удаление повторов и вычисление дельт},\\
|
||||||
|
&\longrightarrow \text{код Голомба--Райса}
|
||||||
|
\longrightarrow \text{Base62-представление}.
|
||||||
|
\end{aligned}
|
||||||
|
\]
|
||||||
|
Итоговая версия имеет вид
|
||||||
|
\[
|
||||||
|
\texttt{set:}\langle b\rangle\langle m\rangle\langle payload\rangle.
|
||||||
|
\]
|
||||||
|
Префикс \texttt{set:} распознаётся RPM как признак специальной версии. Следующие два символа кодируют параметры $b=\texttt{bpp}$ и $m=\texttt{Mshift}$ по правилу $c=v-7+\texttt{'a'}$. Допустимы $10\leq b\leq32$, $7\leq m\leq31$ и $m<b$. Оставшаяся часть строки содержит закодированный в \texttt{Base62} битовый поток.
|
||||||
|
|
||||||
|
\subsection{Хеширование и вероятность коллизий}
|
||||||
|
|
||||||
|
Для каждого имени вычисляется 32-битный Jenkins one-at-a-time [\Ref{JENKINS}], после чего сохраняются только $b$ младших бит. Пусть $n$ различных имён независимо и равномерно отображаются в пространство из $N=2^b$ значений. Тогда математическое ожидание числа столкнувшихся пар равно
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\References
|
||||||
|
\begin{enumerate}
|
||||||
|
\item
|
||||||
|
\Label{SETC}
|
||||||
|
Tourbin A.
|
||||||
|
\emph{set.c --- base62, Golomb and set-string routines}.
|
||||||
|
ALT RPM source code, 2010--2012.
|
||||||
|
[Электронный ресурс] URL: \url{https://git.altlinux.org/gears/r/rpm.git?a=blob;f=lib/set.c}.
|
||||||
|
|
||||||
|
\item
|
||||||
|
\Label{JENKINS}
|
||||||
|
\end{enumerate}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\documentclass[openany, twoside, a4paper, 10pt]{extbook}
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage[english, russian]{babel}
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\usepackage{indentfirst}
|
||||||
|
\frenchspacing
|
||||||
|
\raggedbottom
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\usepackage{url}
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\usepackage{ifpdf}
|
||||||
|
\ifpdf
|
||||||
|
\usepackage[pdftex]{graphicx}
|
||||||
|
\usepackage{cmap}
|
||||||
|
\pdfcompresslevel=9
|
||||||
|
\DeclareGraphicsExtensions{.pdf,.png,.jpg}
|
||||||
|
\else
|
||||||
|
\usepackage[dvips]{graphicx}
|
||||||
|
\DeclareGraphicsExtensions{.eps}
|
||||||
|
\fi
|
||||||
|
\graphicspath{ {./images/} }
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\usepackage{float}
|
||||||
|
\restylefloat{table}
|
||||||
|
\usepackage{multirow}
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\usepackage{amsmath}
|
||||||
|
\usepackage{amssymb}
|
||||||
|
\usepackage{amscd}
|
||||||
|
\usepackage{bm}
|
||||||
|
\usepackage{caption}
|
||||||
|
\usepackage{makecell}
|
||||||
|
\usepackage{nameref}
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\usepackage{titlesec}
|
||||||
|
\titleformat{\section}[block]{\rmfamily\Large\bfseries\filcenter}{\thesection.}{1em}{}
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\sloppy
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
% a5paper: 148 x 210
|
||||||
|
% print area: 110 x 180
|
||||||
|
% top = bottom = (210 - 180) / 2 = 15
|
||||||
|
% left = right = (148 - 110) / 2 = 19
|
||||||
|
\usepackage[%
|
||||||
|
left=5cm,%
|
||||||
|
top=5.85cm,%
|
||||||
|
right=5cm,%
|
||||||
|
bottom=5.85cm,%
|
||||||
|
headsep=0.2cm,%
|
||||||
|
footskip=0.5cm,%
|
||||||
|
]{geometry}
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\usepackage{titlesec}
|
||||||
|
\newpagestyle{lvkpagestyle}{
|
||||||
|
\sethead{}{}{}
|
||||||
|
\setfoot{}{\usepage}{}
|
||||||
|
}
|
||||||
|
\pagestyle{lvkpagestyle}
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\makeatletter
|
||||||
|
\newcommand\Title[2]{%
|
||||||
|
%\par
|
||||||
|
\begin{centering}
|
||||||
|
\medskip
|
||||||
|
{
|
||||||
|
\textbf{#1} \\
|
||||||
|
}
|
||||||
|
{
|
||||||
|
\Large
|
||||||
|
\textbf{\textsc{#2}} \\
|
||||||
|
}
|
||||||
|
\bigskip
|
||||||
|
\end{centering}
|
||||||
|
\@afterheading
|
||||||
|
}
|
||||||
|
\makeatother
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\makeatletter
|
||||||
|
\newcommand{\References}{
|
||||||
|
\medskip
|
||||||
|
\section*{Литература}
|
||||||
|
\nopagebreak
|
||||||
|
\medskip
|
||||||
|
\@afterheading
|
||||||
|
}
|
||||||
|
\makeatother
|
||||||
|
|
||||||
|
\makeatletter
|
||||||
|
\newcommand{\ReferencesEng}{
|
||||||
|
\medskip
|
||||||
|
\section*{References}
|
||||||
|
\nopagebreak
|
||||||
|
\medskip
|
||||||
|
\@afterheading
|
||||||
|
}
|
||||||
|
\makeatother
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\makeatletter
|
||||||
|
\newcommand{\unchapter}[1]{%
|
||||||
|
\begingroup
|
||||||
|
\let\@makechapterhead\@gobble % make \@makechapterhead do nothing
|
||||||
|
\chapter{#1}
|
||||||
|
\endgroup
|
||||||
|
}
|
||||||
|
\makeatother
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\makeatletter
|
||||||
|
\newcommand{\startgroup}[1]{\addtocontents{toc}{\contentsline{chapter}{#1}{}}}
|
||||||
|
\makeatother
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\renewcommand*\thesection{\arabic{section}}
|
||||||
|
\newcommand{\AddRefPrefix}[1]{
|
||||||
|
\renewcommand{\Pageref}[1]{\pageref{#1##1}}
|
||||||
|
\renewcommand{\Ref}[1]{\ref{#1##1}}
|
||||||
|
\renewcommand{\Label}[1]{\label{#1##1}}
|
||||||
|
}
|
||||||
|
%%\newcommand{\Ref}[1]{\ref{#1}}
|
||||||
|
\newcommand{\Pageref}[1]{\pageref{#1}}
|
||||||
|
\newcommand{\Label}[1]{\label{#1}}
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\renewcommand{\thetable}{\arabic{table}}
|
||||||
|
\renewcommand{\thefigure}{\arabic{figure}}
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\usepackage{pdfpages}
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\begin{document}
|
||||||
|
%% \setcounter{page}{3}
|
||||||
|
\setcounter{tocdepth}{0}
|
||||||
|
%% \tableofcontents
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
% \startgroup{Секция 1. Разные вещи}
|
||||||
|
% \unchapter{\textnormal{\textit{Иванов И.И.}} Первая статья в сборнике}
|
||||||
|
% \AddRefPrefix{th1}
|
||||||
|
\input{article_hbd}
|
||||||
|
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
|
\end{document}
|
||||||
|
%% ---------------------------------------------------------------------------
|
||||||
Reference in New Issue
Block a user