⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tech_report.tex

📁 Rsync 3.0.5 source code
💻 TEX
字号:
\documentclass[a4paper]{article}\begin{document}\title{The rsync algorithm}\author{Andrew Tridgell \quad\quad Paul Mackerras\\Department of Computer Science \\Australian National University \\Canberra, ACT 0200, Australia}\maketitle\begin{abstract}  This report presents an algorithm for updating a file on one machine  to be identical to a file on another machine.  We assume that the  two machines are connected by a low-bandwidth high-latency  bi-directional communications link.  The algorithm identifies parts  of the source file which are identical to some part of the  destination file, and only sends those parts which cannot be matched  in this way.  Effectively, the algorithm computes a set of  differences without having both files on the same machine.  The  algorithm works best when the files are similar, but will also  function correctly and reasonably efficiently when the files are  quite different.\end{abstract}\section{The problem}Imagine you have two files, $A$ and $B$, and you wish to update $B$ to bethe same as $A$. The obvious method is to copy $A$ onto $B$.Now imagine that the two files are on machines connected by a slowcommunications link, for example a dialup IP link.  If $A$ is large,copying $A$ onto $B$ will be slow.  To make it faster you couldcompress $A$ before sending it, but that will usually only gain afactor of 2 to 4.Now assume that $A$ and $B$ are quite similar, perhaps both derivedfrom the same original file. To really speed things up you would needto take advantage of this similarity. A common method is to send justthe differences between $A$ and $B$ down the link and then use thislist of differences to reconstruct the file.The problem is that the normal methods for creating a set ofdifferences between two files rely on being able to read both files.Thus they require that both files are available beforehand at one endof the link.  If they are not both available on the same machine,these algorithms cannot be used (once you had copied the file over,you wouldn't need the differences).  This is the problem that rsyncaddresses.The rsync algorithm efficiently computes which parts of a source filematch some part of an existing destination file.  These parts need notbe sent across the link; all that is needed is a reference to the partof the destination file.  Only parts of the source file which are notmatched in this way need to be sent verbatim.  The receiver can thenconstruct a copy of the source file using the references to parts ofthe existing destination file and the verbatim material.Trivially, the data sent to the receiver can be compressed using anyof a range of common compression algorithms, for further speedimprovements.\section{The rsync algorithm}Suppose we have two general purpose computers $\alpha$ and $\beta$.Computer $\alpha$ has access to a file $A$ and $\beta$ has access tofile $B$, where $A$ and $B$ are ``similar''.  There is a slowcommunications link between $\alpha$ and $\beta$.The rsync algorithm consists of the following steps:\begin{enumerate}\item $\beta$ splits the file $B$ into a series of non-overlapping  fixed-sized blocks of size S bytes\footnote{We have found that  values of S between 500 and 1000 are quite good for most purposes}.  The last block may be shorter than $S$ bytes.\item For each of these blocks $\beta$ calculates two checksums:  a weak ``rolling'' 32-bit checksum (described below) and a strong  128-bit MD4 checksum.\item $\beta$ sends these checksums to $\alpha$.  \item $\alpha$ searches through $A$ to find all blocks of length $S$  bytes (at any offset, not just multiples of $S$) that have the same  weak and strong checksum as one of the blocks of $B$. This can be  done in a single pass very quickly using a special property of the  rolling checksum described below.  \item $\alpha$ sends $\beta$ a sequence of instructions for  constructing a copy of $A$.  Each instruction is either a reference  to a block of $B$, or literal data.  Literal data is sent only for  those sections of $A$ which did not match any of the blocks of $B$.\end{enumerate}The end result is that $\beta$ gets a copy of $A$, but only the piecesof $A$ that are not found in $B$ (plus a small amount of data forchecksums and block indexes) are sent over the link. The algorithmalso only requires one round trip, which minimises the impact of thelink latency.The most important details of the algorithm are the rolling checksumand the associated multi-alternate search mechanism which allows theall-offsets checksum search to proceed very quickly. These will bediscussed in greater detail below.\section{Rolling checksum}The weak rolling checksum used in the rsync algorithm needs to havethe property that it is very cheap to calculate the checksum of abuffer $X_2 .. X_{n+1}$ given the checksum of buffer $X_1 .. X_n$ andthe values of the bytes $X_1$ and $X_{n+1}$.The weak checksum algorithm we used in our implementation was inspiredby Mark Adler's adler-32 checksum.  Our checksum is defined by$$ a(k,l) = (\sum_{i=k}^l X_i) \bmod M $$$$ b(k,l) = (\sum_{i=k}^l (l-i+1)X_i) \bmod M $$$$ s(k,l) = a(k,l) + 2^{16} b(k,l) $$where $s(k,l)$ is the rolling checksum of the bytes $X_k \ldots X_l$.For simplicity and speed, we use $M = 2^{16}$.  The important property of this checksum is that successive values canbe computed very efficiently using the recurrence relations$$ a(k+1,l+1) = (a(k,l) - X_k + X_{l+1}) \bmod M $$$$ b(k+1,l+1) = (b(k,l) - (l-k+1) X_k + a(k+1,l+1)) \bmod M $$Thus the checksum can be calculated for blocks of length S at allpossible offsets within a file in a ``rolling'' fashion, with verylittle computation at each point.Despite its simplicity, this checksum was found to be quite adequate asa first-level check for a match of two file blocks.  We have found inpractice that the probability of this checksum matching when theblocks are not equal is quite low.  This is important because the muchmore expensive strong checksum must be calculated for each block wherethe weak checksum matches.\section{Checksum searching}Once $\alpha$ has received the list of checksums of the blocks of $B$,it must search $A$ for any blocks at any offset that match thechecksum of some block of $B$.  The basic strategy is to compute the32-bit rolling checksum for a block of length $S$ starting at eachbyte of $A$ in turn, and for each checksum, search the list for amatch.  To do this our implementation uses asimple 3 level searching scheme.The first level uses a 16-bit hash of the 32-bit rolling checksum anda $2^{16}$ entry hash table.  The list of checksum values (i.e., thechecksums from the blocks of $B$) is sorted according to the 16-bithash of the 32-bit rolling checksum.  Each entry in the hash tablepoints to the first element of the list for that hash value, orcontains a null value if no element of the list has that hash value.At each offset in the file the 32-bit rolling checksum and its 16-bithash are calculated.  If the hash table entry for that hash value isnot a null value, the second-level check is invoked.The second-level check involves scanning the sorted checksum liststarting with the entry pointed to by the hash table entry, lookingfor an entry whose 32-bit rolling checksum matches the current value.The scan terminates when it reaches an entry whose 16-bit hashdiffers.  If this search finds a match, the third-level check isinvoked.The third-level check involves calculating the strong checksum for thecurrent offset in the file and comparing it with the strong checksumvalue in the current list entry.  If the two strong checksums match,we assume that we have found a block of $A$ which matches a block of$B$.  In fact the blocks could be different, but the probability ofthis is microscopic, and in practice this is a reasonable assumption.When a match is found, $\alpha$ sends $\beta$ the data in $A$ betweenthe current file offset and the end of the previous match, followed bythe index of the block in $B$ that matched.  This data is sentimmediately a match is found, which allows us to overlap thecommunication with further computation.If no match is found at a given offset in the file, the rollingchecksum is updated to the next offset and the search proceeds.  If amatch is found, the search is restarted at the end of the matchedblock.  This strategy saves a considerable amount of computation forthe common case where the two files are nearly identical.  Inaddition, it would be a simple matter to encode the block indexes asruns, for the common case where a portion of $A$ matches a series ofblocks of $B$ in order.\section{Pipelining}The above sections describe the process for constructing a copy of onefile on a remote system.  If we have a several files to copy, we cangain a considerable latency advantage by pipelining the process.This involves $\beta$ initiating two independent processes. One of theprocesses generates and sends the checksums to $\alpha$ while theother receives the difference information from $\alpha$ andreconstructs the files. If the communications link is buffered then these two processes canproceed independently and the link should be kept fully utilised inboth directions for most of the time. \section{Results}To test the algorithm, tar files were created of the Linux kernelsources for two versions of the kernel. The two kernel versions were1.99.10 and 2.0.0. These tar files are approximately 24MB in size andare separated by 5 released patch levels.Out of the 2441 files in the 1.99.10 release, 291 files had changed inthe 2.0.0 release, 19 files had been removed and 25 files had beenadded.A ``diff'' of the two tar files using the standard GNU diff utilityproduced over 32 thousand lines of output totalling 2.1 MB.The following table shows the results for rsync between the two fileswith a varying block size.\footnote{All the tests in this section were  carried out using rsync version 0.5}\vspace*{5mm}\begin{tabular}{|l|l|l|l|l|l|l|} \hline{\bf block} & {\bf matches} & {\bf tag}  & {\bf false}  & {\bf data} & {\bf written}  & {\bf read} \\{\bf size}  &               & {\bf hits} & {\bf alarms} &            &                &            \\ \hline \hline300         & 64247         & 3817434    & 948          & 5312200    & 5629158        & 1632284   \\ \hline500         & 46989         & 620013     & 64           & 1091900    & 1283906        & 979384    \\ \hline700         & 33255         & 571970     & 22           & 1307800    & 1444346        & 699564    \\ \hline900         & 25686         & 525058     & 24           & 1469500    & 1575438        & 544124    \\ \hline1100        & 20848         & 496844     & 21           & 1654500    & 1740838        & 445204    \\ \hline\end{tabular}\vspace*{5mm}In each case, the CPU time taken was less than thetime it takes to run ``diff'' on the two files.\footnote{The wall  clock time was approximately 2 minutes per run on a 50 MHz SPARC 10  running SunOS, using rsh over loopback for communication.  GNU diff  took about 4 minutes.}The columns in the table are as follows:\begin{description}\item [block size] The size in bytes of the checksummed blocks.\item [matches] The number of times a block of $B$ was found in $A$.\item [tag hits] The number of times the 16-bit hash of the rolling  checksum matched a hash of one of the checksums from $B$.\item [false alarms] The number of times the 32-bit rolling checksum  matched but the strong checksum didn't.\item [data] The amount of file data transferred verbatim, in bytes.\item [written] The total number of bytes written by $\alpha$,  including protocol overheads. This is almost all file data.\item [read] The total number of bytes read by $\alpha$, including  protocol overheads. This is almost all checksum information.\end{description}The results demonstrate that for block sizes above 300 bytes, only asmall fraction (around 5\%) of the file was transferred. The amounttransferred was also considerably less than the size of the diff filethat would have been transferred if the diff/patch method of updatinga remote file was used.The checksums themselves took up a considerable amount of space,although much less than the size of the data transferred in eachcase. Each pair of checksums consumes 20 bytes: 4 bytes for therolling checksum plus 16 bytes for the 128-bit MD4 checksum.The number of false alarms was less than $1/1000$ of the number oftrue matches, indicating that the 32-bit rolling checksum is quitegood at screening out false matches. The number of tag hits indicates that the second level of thechecksum search algorithm was invoked about once every 50characters.  This is quite high because the total number of blocks inthe file is a large fraction of the size of the tag hash table. Forsmaller files we would expect the tag hit rate to be much closer tothe number of matches.  For extremely large files, we should probablyincrease the size of the hash table.The next table shows similar results for a much smaller set of files.In this case the files were not packed into a tar file first. Rather,rsync was invoked with an option to recursively descend the directorytree. The files used were from two source releases of another softwarepackage called Samba. The total source code size is 1.7 MB and thediff between the two releases is 4155 lines long totalling 120 kB.\vspace*{5mm}\begin{tabular}{|l|l|l|l|l|l|l|} \hline{\bf block} & {\bf matches} & {\bf tag}  & {\bf false}  & {\bf data} & {\bf written}  & {\bf read} \\{\bf size}  &               & {\bf hits} & {\bf alarms} &            &                &            \\ \hline \hline300         & 3727          & 3899       & 0            & 129775     & 153999         & 83948       \\ \hline500         & 2158          & 2325       & 0            & 171574     & 189330         & 50908       \\ \hline700         & 1517          & 1649       & 0            & 195024     & 210144         & 36828        \\ \hline900         & 1156          & 1281       & 0            & 222847     & 236471         & 29048        \\ \hline1100        & 921           & 1049       & 0            & 250073     & 262725         & 23988        \\ \hline\end{tabular}\vspace*{5mm}\section{Availability}An implementation of rsync which provides a convenient interfacesimilar to the common UNIX command rcp has been written and isavailable for download from http://rsync.samba.org/\end{document}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -