背景:

我正在开发一个与数据库有关的程序,我需要按顺序将脏的元数据从内存中刷新到磁盘。
/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

如果我进行写操作,则读取吞吐量为 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

最佳答案



如果您的设备上没有文件系统,而是直接使用该设备进行读/写,那么图片中就没有文件系统缓存。

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



原因:磁盘仅读取数据,它不必返回到偏移量并写入数据,只需减少1个操作即可。



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



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

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

关于c - C磁盘I/O-以文件的相同偏移量读取后进行写入将使读取吞吐量非常低,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32735850/

10-16 17:39