2015-09-23 21 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