約77MBのバイナリファイルがあります。
nupic@nupic-virtualbox:~/VboxSharedFolder/experiments/sync/exp2$ ls -lah src/
total 77M
drwxrwx--- 1 root vboxsf 0 Jun 21 13:31 .
drwxrwx--- 1 root vboxsf 4.0K Jun 21 16:21 ..
-rwxrwx--- 1 root vboxsf 77M May 27 2014 binary.bin
rsync
私はそれがどのように機能するのかを知るために増分アルゴリズム機能を使って遊んだ。アイデアは、バイナリファイルに小さな違いを作成し、さまざまな方法でどのくらいのデータが転送されるかを確認することです。この目的のために、私は非常に単純なスクリプトを作成しました。
#!/bin/bash
# rsync does not trnansfers delta over local by default
sed 's%\x00\x00\x00\x20\x66\x74\x79\x70\x69\x73\x6f\x6d\x00\x00\x02\x00%\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11%' src/binary.bin > dst/binary.bin
strace -f -e trace=read,write -o rw_rsync_local_default.log rsync -avcz --progress src/ dst/
# rsync -no-W should enables delta tranfer no matter if local or remote
sed 's%\x00\x00\x00\x20\x66\x74\x79\x70\x69\x73\x6f\x6d\x00\x00\x02\x00%\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11%' src/binary.bin > dst/binary.bin
strace -f -e trace=read,write -o rw_rsync_local_delta_enabled.log rsync --no-W -avcz --progress src/ dst/
# rsync trnansfers delta over network by default
sed 's%\x00\x00\x00\x20\x66\x74\x79\x70\x69\x73\x6f\x6d\x00\x00\x02\x00%\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11%' src/binary.bin > dst/binary.bin
strace -f -e trace=read,write -o rw_rsync_remote.log rsync -avcz -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" --progress src/ nupic@localhost:/home/nupic/VboxSharedFolder/experiments/sync/exp2/dst/
# scp should transfers whole file not delta
sed 's%\x00\x00\x00\x20\x66\x74\x79\x70\x69\x73\x6f\x6d\x00\x00\x02\x00%\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11%' src/binary.bin > dst/binary.bin
strace -f -e trace=read,write -o rw_scp.log scp src/binary.bin nupic@localhost:/home/nupic/VboxSharedFolder/experiments/sync/exp2/dst/
# cp always transfers whole file not delta
sed 's%\x00\x00\x00\x20\x66\x74\x79\x70\x69\x73\x6f\x6d\x00\x00\x02\x00%\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11%' src/binary.bin > dst/binary.bin
strace -f -e trace=read,write -o rw_cp.log cp src/binary.bin dst/binary.bin
次に、結果を評価するために次のループがあります。
for i in *.log; do
echo $i; cat $i | grep write | awk 'BEGIN {FS="="}{ sum += $2} END {print sum/1024/1024 "MB"}';
echo "###########";
done
結果は次のとおりです。
rw_cp.log
67.8075MB
###########
rw_rsync_local_default.log
146.697MB
###########
rw_rsync_local_delta_enabled.log
66.8765MB
###########
rw_rsync_remote.log
0.0707941MB
###########
rw_scp.log
136.048MB
###########
この5つの実験では、私には2つのことが明らかになりました。
cp
書き込んだバイト数は、元のファイルのサイズ(rw_cp.log
)とほぼ同じです。rsync
ターゲットがリモート(ネットワーク経由)の場合は、増分アルゴリズム(rw_rsync_remote.log
)を使用してください。
私にとって不明な内容は次のとおりです。
rsync
Bothsrc
とdst
onlocalhost
writeの呼び出しが元のファイルサイズ(バイト)の約2倍になるのはなぜですか? (rw_rsync_local_default.log
)--no-W
オプションが指定されたrsync
ようにsrc
デルタだけを送信しない理由dst
localhost
ここなぜまだファイル全体を転送していますか? (rw_rsync_local_delta_enabled.log
)- ボーナスのヒント:
scp
送信されたバイト数が元のファイルサイズの約2倍であるのはなぜですか?いくつかの暗号化があることを知っていますが、2回は私にとって大きな問題のようです(rw_scp.log
)。
答え1
簡単に言えば、主要な質問に答えるrsync
ためにコピーを実行するために2つのプロセス/スレッドを作成し、プロセス間に1つのストリーミングデータがあり、受信プロセスからターゲット文書に異なるストリーミングデータがあるため、バイト数を2倍にするようです。
出力をさらに詳しく見ると、strace
これがわかります。ファイルの先頭のプロセスIDと呼び出しのファイル記述子番号をwrite
使用して、異なる書き込み「ストリーム」を区別できます。
おそらく、これはソースと宛先が同じシステムにあることを除いて、ローカル転送がリモート転送のように機能できるようにするためです。
このようなものを使用すると、strace -e trace=process,socketpair,open,read,write
いくつかのスレッドが生成され、それらの間にソケットペアが生成され、他のスレッドが入出力ファイルを開くことがわかります。
あなたと同様のテストが実行されます。
$ rm test2
$ strace -f -e trace=process,socketpair,open,close,dup,dup2,read,write -o rsync.log rsync -avcz --progress test1 test2
$ ls -l test1 test2
-rw-r--r-- 1 itvirta itvirta 81920004 Jun 21 20:20 test1
-rw-r--r-- 1 itvirta itvirta 81920004 Jun 21 20:20 test2
各スレッドが個別に書き込んだバイト数を計算してみましょう。
$ for x in 15007 15008 15009 ; do echo -en "$x: " ; grep -E "$x (<... )?write" rsync.log | awk 'BEGIN {FS=" = "} {sum += $2} END {print sum}' ; done
15007: 81967265
15008: 49
15009: 81920056
これは上記の理論と非常に一致しています。最初のスレッドが書き込む他の40kBが何であるかを確認しませんでしたが、rsyncがもう一方の端に転送する必要がある同期ファイルのメタデータとともに進行出力を印刷するとします。
確認はしませんが、デルタ圧縮が有効になっていても、rsyncの「リモート」側はまだファイルを完全に書き込んでおり、cpとほぼ同じ量の書き込みが発生することを示唆しています。 rsyncスレッド間の転送は小さいですが、最終出力は依然として同じです。
答え2
デフォルトでは、さまざまなセキュリティ上の理由から、rsyncは最初にターゲットファイルの新しいコピーを作成してからそれを置き換えます。--inplace
とを指定して上書きできます--no-whole-file
。これは、rsyncがターゲットファイルの内部編集を実行し、マニュアルページに文書化されたさまざまなリスク(この場合は一般的にマイナーなリスク)に対応するように指示します。