【发布时间】:2015-12-20 13:14:03
【问题描述】:
背景:
我正在开发一个与数据库相关的程序,我需要按顺序将脏元数据从内存刷新到磁盘。 /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);
问题会得到缓解,请参阅chart。
【问题讨论】:
-
你的块大小是多少?您很有可能会看到硬件缓存和预读对您正在访问的磁盘的影响。
pwrite()填充缓存,如果下一个pread()用于不同的数据,则不会缓存。在pwrite()之后执行pread()可以直接从磁盘的硬件缓存中读取数据。 -
不知道物理块大小,我在程序中设置为256KB。感谢您的评论,现在我认为这很可能是由磁盘缓冲区引起的。
标签: c performance read-write throughput disk-io