2015-09-23 19 views
7

背景:C盘I/O - 写出同一文件的偏移后将使读取吞吐量很低

我正在开发一个数据库相关的程序,我需要刷新脏的元数据内存到磁盘顺序。 /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后做PREAD,写吞吐量115 MB/s的,和读取吞吐量是208 MB/s的。 ()/ write()和aio_read()/ aio_write(),但问题依然存在。我不知道为什么在一个文件的相同位置读取后写入会使读取吞吐量如此之低。

如果同时接入多块,这样

pread(file, buffer, num_blocks * block_size, i*block_size); 

的问题会缓解,请参阅chart

+1

你的块大小是多少?您很可能会看到硬件缓存和预读对您正在访问的磁盘的影响。 'pwrite()'填充缓存,如果下一个'pread()'用于不同的数据,则不会缓存它。在'pwrite()'之后执行'pread()'操作可以直接从磁盘的硬件缓存中读取数据。 –

+0

我不知道物理块的大小,我在程序中设置为256KB。感谢您的评论,现在我认为这很可能是由磁盘缓冲区引起的。 – Leo

回答

2

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

如果您没有设备上的文件系统并直接使用设备读取/写入,那么没有文件系统缓存出现在图片中。

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

我发现,如果我不这样做PWRITE,读取吞吐量为125 MB/s的

原因:硬盘只是读取数据时,不必回到偏移和写入数据,减少1次操作。

如果我做pwrite,读吞吐量将是21 MB/s,写吞吐量是169 MB/s。

原因:您的磁盘可能具有更好的写入速度,可能磁盘缓冲区是缓存写入而不是直接点击媒体。

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

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

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

+0

感谢您的回答,现在我认为这很可能是由磁盘缓冲区引起的。 但我仍然无法想象只是寻求到以前的位置将让读吞吐量从125 MB /秒降至21 MB /秒... – Leo

+0

@leo,是的,寻求代价很高。查看IO吞吐量下降时的IO等待时间。 – Rohan