背景:
我正在开发一个与数据库相关的程序,我需要按顺序将脏元数据从内存刷新到磁盘。/dev/sda1 是卷格式,因此 /dev/sda1 上的数据将被逐块访问,如果顺序访问,这些块在物理上是相邻的。而且我使用的是直接I/O,所以I/O会绕过文件系统的缓存机制,直接访问磁盘上的块。
问题:
打开 /dev/sda1 后,我将读取一个块,更新该块并将该块写回与 /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 之后进行预读,则写入吞吐量为115 MB/s,读取吞吐量为208 MB/s。
我也试过 read()/write() 和 aio_read()/aio_write(),但问题依旧。我不知道为什么在文件的同一位置读取后写入会使读取吞吐量如此之低。
如果一次访问更多块,像这样
pread(file, buffer, num_blocks * block_size, i*block_size);
问题会缓解,请看图表。