web-dev-qa-db-ja.com

DDがファイルへの書き込みよりもディスクへの書き込みに直接時間がかかるのはなぜですか

Red Hat Enterprise Linux Serverリリース6.4(Santiago)を搭載したシステムのディスクに直接書き込むのと比較して、GPFSファイルシステムのファイルに書き込むときの総書き込み速度を比較しようとしています。私のアプリケーションでは、キャッシュを利用せずに生のレートを測定する必要があります。キャッシュをバイパスするためにddで使用される直接オプションの影響を理解していません。ブロックデバイスに直接書き込む場合、oflag=directを使用すると、GPFSファイルシステムのファイルに書き込む場合と比べて、レートが大幅に低下します。なぜこれが起こるのですか?

総レートを測定するために、ブロックデバイスまたはファイルに同時に書き込むpを実行するddプロセスを作成します。次に、得られたpレートを合計して、合計書き込みレートを取得します。

    #!/bin/bash
    directdiskrate=~/scratch/rate5
    syncdiskrate=~/scratch/rate4
    filerate=~/scratch/rate3
    numruns=1
    numthreads=30

    #to disk use both conv=fsync and oflag=direct
    writetodiskdirect="dd if=/dev/zero of=/dev/sdac bs=256k count=4096 conv=fsync oflag=direct iflag=fullblock"
    for p in $(seq $numthreads)
    do
             #parses output of dd, rate is on last line, each field separated by ,s
            $writetodiskdirect 2>&1|tail -n 1|awk 'BEGIN { FS = "," } ; { print $3 }'|sed -e 's/MB\/s//g'>>$directdiskrate&
    done
    wait

    #to disk use only conv=fsync option
    writetodisksync="dd if=/dev/zero of=/dev/sdac bs=256k count=4096 conv=fsync iflag=fullblock"
    for p in $(seq $numthreads)
    do
       #parses output of dd, rate is on last line, each field separated by ,s
       $writetodisksync 2>&1|tail -n 1|awk 'BEGIN { FS = "," } ; { print $3 }'|sed -e 's/MB\/s//g'>>$syncdiskrate&
    done
    wait

    #to file use both conv=fsync and oflag=direct
    for p in $(seq $numthreads)
    do
        writetofile="dd if=/dev/zero of=/gpfs1/fileset6/file$p bs=256k count=4096 conv=fsync oflag=direct"
        #parses output of dd, rate is on last line, each field separated by ,s
        $writetofile 2>&1|tail -n 1|awk 'BEGIN { FS = "," } ; { print $3 }'|sed -e 's/MB\/s//g'>>$filerate&
    done
    wait

結果: 30プロセスのそれぞれの書き込み速度は次のとおりです。

  1. conv=fsyncオプションを使用してディスクに書き込むと、各プロセスの書き込み速度は〜180MB/sになります
  2. conv=fsyncoflag=directの両方を使用してディスクに書き込む場合、各プロセスの書き込み速度は最大9MB /秒です
  3. conv=fsyncoflag=directの両方を使用してGPFSファイルシステム内のファイルに書き込む場合、書き込み速度は最大80MB/sになります。
7
user3216949

この違いは間違いなく1つのこと、つまりキャッシングに帰着します。

同期書き込みを取得するトリックを実行しない限り、特にユーザーランドからの場所を特定することは本当に困難ですが、すべてのLinuxカーネルは(キャッシュ)ファイルシステムの書き込みをバッファリングします。つまり、カーネルはddが送信するデータをカーネルメモリのどこかにあるファイルに保存します。カーネルはおそらくファイルシステムコードを使用してこれを行います。将来、カーネルはディスクブロックをスケジュールしてディスクに移動します。これは、カーネルがddに書き込みが完了したことを通知した後、「非同期に」発生します。

これは、バスを介してディスクドライブにバイトを移動してからディスクプラッターに移動する方が、ユーザーからカーネルメモリにコピーするよりもはるかに遅いためです。通常、プログラムは、「書き込んだ」データがしばらくディスクに書き込まれないことをあまり気にしません。ハードウェアの信頼性は十分高いため、データはほとんど常にPlatterに到達します。

これは簡単な答えですが、カーネルでバッファリングされたすべての読み取り/書き込み/削除を取得すると、ファイルシステムコードは、削除されるファイルのデータを書き込まないようにすることで、ファイルの寿命を短くすることができます。ディスク。ファイルシステムコードは、書き込みをグループ化して、書き込みのグループよりも大きいディスクブロックを利用し、それらを1つの書き込みに統合できます。ほとんどのファイルシステムで実行できる大量の最適化があります。

5
Bruce Ediger

コピープログラムのディスクキャッシュは、私が想定しているddを使用するよりも速くなります。

これがディスクを集中的に使用する唯一のアプリである場合は、プログラムが終了するまで待ってから実行します。

$ sync; sync 

これにより、キャッシュがすぐにフラッシュされます。プロンプトに戻るまでに時間がかかる場合は、キャッシュにヒットしていたことがわかります。

私はこれをUSBドライブをプルする前に行い、多くの場合、コピーが完了してからキャッシュがディスクにアクセスするまでにかなり長い時間がかかります。

2
rking