1TBファイルがあります。バイト 12345678901 からバイト 19876543212 まで読み込み、100 MB RAM のコンピュータの stdout に保存したいと思います。
これを行うには、Perlスクリプトを簡単に作成できます。 sysread は 700 MB/s を提供しますが (良好)、syswrite は 30MB/s だけを提供します。私はもっと効率的なものが欲しいです。可能であれば、すべてのUnixシステムにインストールされ、1GB / sを提供できることを望みます。
私の最初の考えは次のとおりです。
dd if=1tb skip=12345678901 bs=1 count=$((19876543212-12345678901))
しかし、これはそれほど効率的ではありません。
編集する:
syswriteエラーをどのように測定したのかわかりません。これは3.5GB / sを提供します。
perl -e 'sysseek(STDIN,shift,0) || die; $left = shift; \
while($read = sysread(STDIN,$buf, ($left > 32768 ? 32768 : $left))){ \
$left -= $read; syswrite(STDOUT,$buf);
}' 12345678901 $((19876543212-12345678901)) < bigfile
そしてyes | dd bs=1024k count=10 | wc
悪夢を避けてください。
ベストアンサー1
ブロックサイズが小さいため、遅くなります。最新のGNU dd
(Coretils v8.16+)、最も簡単な方法は、skip_bytes
オプションcount_bytes
を使用することです。
in_file=1tb
start=12345678901
end=19876543212
block_size=4096
copy_size=$(( $end - $start ))
dd if="$in_file" iflag=skip_bytes,count_bytes,fullblock bs="$block_size" \
skip="$start" count="$copy_size"
修正する
fullblock
上記で追加したオプション@ギルズの答え。最初はこれが暗示的なものかもしれないと思ったが、count_bytes
そうではなかった。
言及された問題は以下の潜在的な問題です。dd
何らかの理由で読み取り/書き込み呼び出しが中断されると、データは失われます。ほとんどの場合、そうではない可能性があります(パイプではなくファイルから読み取られるため、確率が低下します)。
andオプションdd
なしでaを使用することはより困難です。skip_bytes
count_bytes
in_file=1tb
start=12345678901
end=19876543212
block_size=4096
copy_full_size=$(( $end - $start ))
copy1_size=$(( $block_size - ($start % $block_size) ))
copy2_start=$(( $start + $copy1_size ))
copy2_skip=$(( $copy2_start / $block_size ))
copy2_blocks=$(( ($end - $copy2_start) / $block_size ))
copy3_start=$(( ($copy2_skip + $copy2_blocks) * $block_size ))
copy3_size=$(( $end - $copy3_start ))
{
dd if="$in_file" bs=1 skip="$start" count="$copy1_size"
dd if="$in_file" bs="$block_size" skip="$copy2_skip" count="$copy2_blocks"
dd if="$in_file" bs=1 skip="$copy3_start" count="$copy3_size"
}
さまざまなブロックサイズを試してみることもできますが、その効果は劇的ではありません。バラより -ddのbsパラメータに最適な値を決定する方法はありますか?