C磁盘I/O - 在读取文件的相同偏移量后写入将使读取吞吐量非常低

Chi*_*hia 7 c performance read-write disk-io throughput

背景:

我正在开发一个与数据库相关的程序,我需要按顺序将脏元数据从内存刷新到磁盘./ dev/sda1是volumn格式,因此将逐块访问/ 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);
}
Run Code Online (Sandbox Code Playgroud)

我发现如果我不做pwrite,读取吞吐量是125 MB/s.

如果我执行pwrite,读取吞吐量将为21 MB/s,写入吞吐量为169 MB/s.

如果我在pwrite之后pread,写吞吐量是115 MB/s,读吞吐量是208 MB/s.

我也试过read()/ write()和aio_read()/ aio_write(),但问题仍然存在.我不知道为什么在读取文件的相同位置后写入会使读取吞吐量如此之低.

如果一次访问更多的块,就像这样

pread(file, buffer, num_blocks * block_size, i*block_size);
Run Code Online (Sandbox Code Playgroud)

问题会缓解,请参阅图表.

Roh*_*han 3

而且我使用直接I/O,因此I/O会绕过文件系统的缓存机制,直接访问磁盘上的块。

如果设备上没有文件系统并直接使用设备进行读/写,则不会出现文件系统缓存。

您观察到的行为是典型的磁盘访问和 IO 行为。

我发现如果我不做pwrite,读取吞吐量是125 MB/s

原因:磁盘只是读取数据,不需要回到偏移量写入数据,少了1次操作。

如果我执行 pwrite,读取吞吐量将为 21 MB/s,写入吞吐量为 169 MB/s。

原因:您的磁盘可能具有更好的写入速度,可能磁盘缓冲区正在缓存写入而不是直接命中介质。

如果我在 pwrite 之后进行 preread,则写入吞吐量为 115 MB/s,读取吞吐量为 208 MB/s。

原因:写入的数据很可能在磁盘级别缓存,因此读取从缓存而不是介质中获取数据。

为了获得最佳性能,您应该使用异步 IO 和一次块数。但是,您必须使用合理数量的块,并且不能使用非常大的数量。应该通过反复试验找出最佳方案。