2009-06-01 116 views
4

我得到一個程序,需要檢查一個文件的塊是歸零還是有數據。這個alg運行整個文件的大小達幾個演出,需要一段時間才能運行。有沒有更好的方法來檢查它是否歸零?檢查內存是否歸零的最快方法

平臺:Linux和Windows

bool WGTController::isBlockCompleted(wgBlock* block) 
{ 
    if (!block) 
     return false; 

    uint32 bufSize = (uint32)block->size; 
    uint64 fileSize = UTIL::FS::UTIL_getFileSize(m_szFile); 

    if (fileSize < (block->size + block->fileOffset)) 
     return false; 

    char* buffer = new char[bufSize]; 

    FHANDLE fh=NULL; 

    try 
    { 
     fh = UTIL::FS::UTIL_openFile(m_szFile, UTIL::FS::FILE_READ); 
     UTIL::FS::UTIL_seekFile(fh, block->fileOffset); 
     UTIL::FS::UTIL_readFile(fh, buffer, bufSize); 
     UTIL::FS::UTIL_closeFile(fh); 
    } 
    catch (gcException &) 
    { 
     SAFE_DELETEA(buffer); 
     UTIL::FS::UTIL_closeFile(fh); 
     return false; 
    } 

    bool res = false; 

    for (uint32 x=0; x<bufSize; x++) 
    { 
     if (buffer[x] != 0) 
     { 
      res = true; 
      break; 
     } 
    } 

    SAFE_DELETEA(buffer); 
    return res; 
} 
+0

這個算法看起來有點「蠻力」。有沒有一種很好的方法來確定接下來的n個字節是否會有值?如果不是,這可能是您最好的選擇(除了在文件中讀取時可能發生的文件爭用)。 – 2009-06-01 04:49:54

+0

也許你的程序可能會假設塊沒有被清除,除非明確這麼做?我的意思是,如果一個塊需要清除,你的程序可以注意到這一點並清除數據(並且注意塊清楚)。我想我只是好奇你爲什麼想首先解決這個問題。 – 2009-06-01 05:00:06

+1

這裏的「真正的」問題是爲什麼你需要首先掃描文件爲零。也許你可以重新設計你的系統,這樣就不需要這種無用的掃描,而不是試圖提高速度。 – lothar 2009-06-01 16:23:48

回答

6

有多長 '一段時間'? ...我會說試圖比較儘可能多的並行值會有所幫助,也許使用一些SIMD指令來比較一次超過4個字節?

請記住雖然,無論你如何快速作出比較,最終的數據仍然需要從文件中讀取。如果文件尚未存儲在內存中的某個緩存中,那麼在磁盤帶寬飽和之前,您可能最多隻能限制在100-150 MB/s的數量級。如果你已經達到這一點,那麼你可能首先需要考慮一種避免加載文件的方法,或者只是接受它不會比這更快的事實。

2

在文件/塊,其中更可能有非零值有地方呢?您只需要找到一個非零值(您的中斷條件),因此請首先查找最可能找到它們的位置 - 這不一定是文件/塊的開始。根據實際應用情況,最後開始可能有意義,或檢查中間的1/3。

但是,我不建議隨機跳到不同的位置;從磁盤讀取可能會變得令人難以置信;)..

0

我想看到這個功能的組件輸出。 你可以做的事情會加速很多是使用SSE指令。通過這些指令,您可以一次加載8個字節,全部檢查爲零並繼續。 你也可以展開循環幾次。

0

您ALGO看起來不錯,但你可以嘗試着優化,如果你事先你會得到什麼類型的文件稱爲起點......但話又說回來,如果它是一個特定的文件,最有可能的信息將在頭(前幾個字節)。

還要確保塊級>尺寸是誰調用該方法:)

還檢查了Boost的內存映射文件的設施......這可能是一種幫助,這取決於你如何計算不是1最佳塊級>尺寸

0

我對你的「開箱即用」的答案,但我不知道它是如何feasable在您的情況來實現。

如果您不控制轉儲過程:由於它是一個在excpetional情況下生成的大型恢復(轉儲?)文件,爲什麼不在轉儲後立即掃描低優先級的文件(對於0字節)以某種方式標記它爲更快的後來識別? (或者你可以壓縮它並在以後解析/掃描zip文件)

或者如果你控制轉儲過程:(一個緩慢的過程,你必須做任何反正)爲什麼不指出在轉儲文件的末尾如果轉儲文件填充0或具有一些有效數據(因爲您已經寫入並且知道其中的內容)?就像你不必爲兩次I/O開銷付費一樣。

這裏的目標是使讀取由deffering的procss另一個eralier時間要快得多,因爲當轉儲發生時,有不太可能是運營商在等待它加載。

0

首先,不要每次都分配一個新的緩衝區。分配一個(每個線程)並重新使用它。使用一個很好的大塊,並做多個讀取/檢查通行證。
二,不要比較每個字符。對較大的整數類型進行比較。最有可能你會想要一個32位int,但取決於你的操作系統/編譯器,它可能會更快地使用64甚至128位int。使用32位int,您可以將比較次數減少4倍。當然,你的意願不得不擔心結束條件。爲此,如果您正在比較的緩衝區不是int大小的偶數倍,那麼很容易,只需在執行比較之前將最後的X個字節設置爲0即可。第三,它可能會幫助你的編譯器展開循環。在循環體中做4或8次比較。這應該有助於編譯器優化一點,並減少退出循環的比較次數。確保您的緩衝區是比較類型的倍數x循環中的比較次數。第四,使用(* pBuffer ++)而不是緩衝區[i]會更快,尤其是如果緩衝區很大。

對於其中的任何一種情況,您當然會想要獲得一些指標並查看實際的幫助。

0

我會告訴你一個骯髒的,不可移植的和困難的方法,但可以更高效......如果你正在處理稀疏文件,你真的很無聊,想要搗亂你的文件系統的內部使用時,可以嘗試添加一個新的函數,該函數返回一個位圖,指示哪些塊被映射,哪些不是(未映射的那些被清零,其餘的則需要手動檢查)。

是的,我知道這是瘋狂的,沒有人會喜歡做這樣的事情xD

相關問題