1

レコードが永続化されたと報告したときに、それが実際に永続化されたものであることを可能な限り保証するアプリが必要です。これを行うには を使用することを理解していますfsync(fd)。しかし、何らかの奇妙な理由で、fsync() を使用すると、ディスクに書き込むコードが期待どおりに遅くなるのではなく、速度が上がるようです。

一部のサンプル テスト コードは、次の結果を返します。

no sync() seconds:0.013388   writes per second:0.000001 
   sync() seconds:0.006268   writes per second:0.000002

以下は、これらの結果を生成するコードです。

#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>

void withSync() {
    int f = open( "/tmp/t8" , O_RDWR | O_CREAT );
    lseek (f, 0, SEEK_SET );
    int records = 10*1000;
    clock_t ustart = clock();
    for(int i = 0; i < records; i++) {
        write(f, "012345678901234567890123456789" , 30);
        fsync(f);
    }
    clock_t uend = clock();
    close (f);
    printf("   sync() seconds:%lf   writes per second:%lf\n", ((double)(uend-ustart))/(CLOCKS_PER_SEC), ((double)records)/((double)(uend-ustart))/(CLOCKS_PER_SEC));
}

void withoutSync() {
    int f = open( "/tmp/t10" , O_RDWR | O_CREAT );
    lseek (f, 0, SEEK_SET );
    int records = 10*1000;
    clock_t ustart = clock();
    for(int i = 0; i < records; i++) {
        write(f, "012345678901234567890123456789" , 30 );
    }
    clock_t uend = clock();
    close (f);
    printf("no sync() seconds:%lf   writes per second:%lf \n", ((double)(uend-ustart))/(CLOCKS_PER_SEC), ((double)records)/((double)(uend-ustart))/(CLOCKS_PER_SEC));
}

int main(int argc, const char * argv[])
{
    withoutSync();
    withSync();
    return 0;
}
4

2 に答える 2

9

問題は、I/O書き込みの時間を計ろうとしている方法にあります。意味的には、I / Oレコードの書き込み間の実時間clockを測定したいのですが、合計経過時間ではなくCPU実行時間を測定するCライブラリ関数を使用しています。または、理想的には(後者はLinux拡張機能です)clock_gettimeのクロック選択で使用します。CLOCK_MONOTONICCLOCK_MONOTONIC_RAW

呼び出しの間に経過した合計時間を収集していませんclock:プロセスがCPUサイクルを回転させていた時間の見積もりを収集しています。ディスクI/O(具体的には、とへの呼び出しの両方writefsyncがブロックされています。つまり、これらのシステムコールはそれぞれ、カーネルによって処理され、プロセスコンテキスト内でCPUを消費しません。したがって、実世界で経過した合計時間である実時間の実際の差を測定する必要があります。これは、テストプログラムのプロセスの範囲外です。確かに、あなたが心配しているのはCPU時間ではありませんfsync。I / O操作の実行時間のほとんどは、カーネルまたはCPUによっても処理されません。ディスクコントローラが原因です。

さらに、小さなレコードサイズはベンチマークとしてOKです。これは、同期されたI / Oの一般的な使用例です(トランザクションログのメタデータの書き込みなど)。より大きなレコードサイズのタイミングの安定性を得るには、タイマー間隔ごとにループの反復回数を大幅に増やし、平均化/償却します。これにより、同期して書き込まれ、フラッシュされる小さなブロッキングレコードのコストが正確にモデル化されます。

fdatasyncパフォーマンスの向上を検討してください。

于 2012-11-12T04:00:10.447 に答える
0

コメントありがとうございます。テストをより多くのトランザクションに増やすことを提案するコメントは正しいです。より多くのトランザクションを使用fsync()すると、何かを行うように見えます。少なくとも OS/X 10.8 では:

  1. 書き込みによってファイル サイズが増加しない場合、書き込みがfsync()完了するまでの時間が 2 倍になります。
  2. 書き込みによってファイル サイズが増加すると、大幅にfsync()遅くなります。
于 2012-11-12T03:06:17.170 に答える