バックグラウンド:
データベース関連のプログラムを開発しており、ダーティ メタデータをメモリからディスクに順次フラッシュする必要があります。/dev/sda1 はボリューム形式なので、/dev/sda1 上のデータはブロックごとにアクセスされ、シーケンシャルにアクセスするとブロックは物理的に隣接します。また、ダイレクト I/O を使用しているため、I/O はファイル システムのキャッシュ メカニズムをバイパスし、ディスク上のブロックに直接アクセスします。
問題:
/dev/sda1 を開いた後、1 つのブロックを読み取り、ブロックを更新して、ブロックを /dev/sda1 の先頭からの同じオフセットに繰り返し書き込みます。
コードは以下のようなものです -
//block_size = 256KB
int file = open("/dev/sda1", O_RDWR|O_LARGEFILE|O_DIRECT);
for(int i=0; i<N; i++) {
pread(file, buffer, block_size, i*block_size);
// Update the buffer
pwrite(file, buffer, block_size, i*block_size);
}
pwrite を実行しない場合、読み取りスループットは125 MB/sであることがわかりました。
pwrite を実行すると、読み取りスループットは21 MB/sになり、書き込みスループットは169 MB/sになります。
pwrite の後に read を行うと、書き込みスループットは115 MB/sで、読み取りスループットは208 MB/sです。
read()/write() と aio_read()/aio_write() も試しましたが、問題は残ります。ファイルの同じ位置で読み取り後に書き込みを行うと、読み取りスループットが非常に低くなる理由がわかりません。
このように、一度により多くのブロックにアクセスする場合
pread(file, buffer, num_blocks * block_size, i*block_size);
問題は軽減されます。チャートを参照してください。