2009-08-10 181 views
2

我正在忙着寫一些東西來測試Linux上磁盤IO的讀取速度。讀取二進制文件,Linux緩衝區緩存

目前,我有這樣的事情來讀取文件:

編輯以更改代碼這樣:

const int segsize = 1048576; 
    char buffer[segsize]; 
    ifstream file; 
    file.open(sFile.c_str()); 
    while(file.readsome(buffer,segsize)) {} 

對於foo.dat,這是150GB,我第一次讀它大約需要2分鐘。 但是,如果我在第一次運行的60秒內運行它,則需要大約3秒的時間才能運行。這怎麼可能?當然,唯一可以從這個快速讀取的地方是RAM中的緩衝區緩存,並且該文件太大而無法放入RAM中。

該機器具有50GB的RAM,並且該驅動器是具有所有默認設置的NFS安裝。請讓我知道我在哪裏可以確認這個文件實際上是以這種速度讀取的?我的代碼錯了嗎?第一次讀取文件時似乎需要一段正確的時間。

編輯爲添加: 發現我的文件只能讀取到一個隨機點。我已經設法通過從1048576將segsize降低到1024來解決這個問題。我不知道爲什麼改變它可以讓ifstream讀取整個文件,而不是在隨機點停止。

感謝您的答案。

+0

爲什麼你認爲整個文件必須適合緩存? – 2009-08-10 13:20:51

+0

當我第一次讀取文件時,它幾乎完全是IO綁定,130s WALL,3s CPU,當我第二次讀取文件時,CPU和WALL的時間幾乎完全相同,表明沒有IO足夠接近。 – Salgar 2009-08-10 13:24:25

回答

1

in_avail返回流讀取緩衝區中可讀取多少的下限,而不是文件的大小。要通過流讀取整個文件,只需保持 調用流的readsome()方法並檢查使用gcount()方法讀取了多少內容 - 當該方法返回零時,您已經讀取了everthing。

+0

如果showmanyc()(如果緩衝區爲空,它是由in_avail調用的虛擬成員)返回0,則該算法將停止。但showmanyc()可以返回0而不會到達文件結尾。 (Linux的版本爲filebuf返回文件大小,Solaris和AIX返回0) – AProgrammer 2009-08-10 13:59:34

3
  • in_avail不給該文件的長度,但下界什麼是可用的(尤其是如果緩衝區已經被使用,它返回緩衝區中可用的大小)。它的目標是要知道什麼可以不受阻礙地閱讀。

  • unsigned int很可能無法保存超過4GB的長度,所以讀取的內容很可能在緩存中。

  • C++0x Stream Positioning如果你正在使用大文件

+0

嗨,關於unsigned int的好處。我編輯了我的代碼以反映您所說的內容。我仍然遇到同樣的問題。事實上,我也寫了一個perl腳本,它只讀取整個文件並得到類似的結果(兩個部分都比較慢)。第一次運行只需2分鐘,第二次運行只需3秒鐘。 – Salgar 2009-08-10 13:57:03

4

在Linux上,你可以快速的吞吐量測試做到這一點可能是有趣的你:

$ dd if=/dev/md0 of=/dev/null bs=1M count=200 
200+0 records in 
200+0 records out 
209715200 bytes (210 MB) copied, 0.863904 s, 243 MB/s 

$ dd if=/dev/md0 of=/dev/null bs=1M count=200 
200+0 records in 
200+0 records out 
209715200 bytes (210 MB) copied, 0.0748273 s, 2.8 GB/s 

$ sync && echo 3 > /proc/sys/vm/drop_caches 

$ dd if=/dev/md0 of=/dev/null bs=1M count=200 
200+0 records in 
200+0 records out 
209715200 bytes (210 MB) copied, 0.919688 s, 228 MB/s 

echo 3 > /proc/sys/vm/drop_caches將適當清空緩存

+0

請注意,如果數據未被修改,則在刪除緩存之前進行同步並不是嚴格必要的 - drop_caches不會刪除髒(或mmap)的數據。 – bdonlan 2009-08-10 15:22:09

+0

請注意,這需要超級用戶權限。 – 2009-08-29 12:18:59

1

它似乎需要一個正確的時間第一次fil e被讀取。

在第一次閱讀時,您在大約2分鐘內讀取150GB。這可以達到每秒10吉比特。這就是你期望的(基於網絡到你的NFS掛載)?

+0

事實證明這是正確的答案,存在這種差異的原因是因爲我正在閱讀的所有內容都將其放入緩存中。 問題是我沒有讀入緩存中的所有內容。 例如,當讀取一個10GB的文件。我讀取大小並加起來.readsome()已經讀取,我得到了很大的改變。 大小= 10819423232 閱讀= 2229490000 任何人都知道why()會提前停止? – Salgar 2009-08-10 15:03:50

+0

健康檢查你的號碼總是好的。 你需要編寫自己的程序來做到這一點嗎?如果我想測量讀取1MB大塊文件的時間,我只需要使用dd ... – 2009-08-10 15:12:15

1

一種可能性是該文件可能至少部分是稀疏的。稀疏文件具有真正爲空的區域 - 它們甚至沒有分配給它們的磁盤空間。這些稀疏區域也不會消耗太多緩存空間,因此讀取稀疏區域基本上只需要時間來將讀入的用戶空間頁面歸零。

您可以用ls -lsh查詢。第一列將是磁盤上的大小 - 如果小於文件大小,則文件確實稀疏。要解除文件的稀疏,只需寫入它的每一頁。

如果您想測試真正的磁盤速度,可以選擇使用O_DIRECT標誌open(2)繞過緩存。請注意,使用O_DIRECT的所有IO必須是頁面對齊的,並且一些文件系統不支持它(特別是,它不能在NFS上運行)。另外,除了基準測試之外,這是一個糟糕的主意。請參閱this thread中的一些Linus的咆哮。

最後,刪除所有緩存在Linux系統上進行測試,你可以這樣做:

echo 3 > /proc/sys/vm/drop_caches 

如果你這樣做客戶端和服務器上,你將迫使文件的內存不足。當然,這會對當時運行的其他任何東西產生負面的性能影響。

相關問題