2012-12-16 82 views
1

我正在寫一個延遲敏感的應用程序,它在初始化時讀取一個文本文件。我已經成型,並重新寫了我所有的算法,使得我的執行時間的85%是從線:更快的方式來讀取文件比boost :: file_mapping?

boost::interprocess::file_mapping file(Path, read_only); 
boost::interprocess::mapped_region data(file, read_only); 

我對Windows的是有映射文件到內存中的任何更快的方法寫這個?可移植性不是一個問題。

+1

請記住,磁盤I/O是許多訂單幅度比內存I/O慢。 –

回答

3

你可以只使用Win32的原生功能,但我想你不會節省很多,因爲升壓不會增加的開銷很多:

OFSTRUCT ofStruct; 
ofStruct.cBytes=sizeof (OFSTRUCT); 
HANDLE file=(HANDLE)OpenFile(fileName, &ofStruct, OF_READ); 
if (file==INVALID_HANDLE_VALUE) 
    handle errors 
else { 
    HANDLE map=CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, 0); 
    if (map==INVALID_HANDLE_VALUE) 
    handle errors 
    else { 
    const char *p=(const char *)MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0)); 
    if (p) { 
     // enjoy using p to read access file contents. 
    } 
    // close all that handles now... 
    } 
+1

不僅如此,但如果OP廣泛使用boost,他將不得不編碼所有已升級的樣板代碼,以將其基於boost的代碼與其winapi數據加載例程接口。 – didierc

1

我建議下探文件映射的想法。

FM是一個複雜的構造,並增加了一些開銷。普通緩存讀取還涉及與物理設備的非平凡交互。你可以做無緩衝的讀取。可能接下來要問的是你實際需要什麼樣的IO--文件有多大?它是順序的嗎?它在網絡上嗎?你有硬件的選擇,還是在客戶的機器上?

+0

文件很小,這就是爲什麼我將它們讀入內存的原因。你能夠舉一個無緩衝的方法的例子嗎?我只需要儘可能快地讀取文件。 – mezamorphic

+0

如果文件很小,則更有理由避免映射到內存。請參閱CreateFile文檔和NO_BUFFERING標誌部分。 –

1

如果文件很小,只需打開並使用標準的Win32 CreateFile()/ ReadFile()API將它們讀入內存。

如果您按順序使用每個文件(或者可以按照您的方式排列代碼),則應該指定FILE_FLAG_SEQUENTIAL_SCAN。這是文件/緩存子系統積極預讀的提示。對於小文件,在第一次調用ReadFile()之前,該文件可能會被讀入緩存中。

編輯:按照要求,下面是說明讀取文件的內容到使用Win32 API字節的載體的片段:

void ReadFileIntoBuffer(const std::wstring& fileName, std::vector<uint8_t>& output) 
{ 
    HANDLE hFile(INVALID_HANDLE_VALUE); 
    try 
    { 
     // Open the file. 
     hFile = CreateFile(filename.c_str(), 
           GENERIC_READ, 
           FILE_SHARE_READ, 
           NULL, 
           OPEN_EXISTING, 
           FILE_FLAG_SEQUENTIAL_SCAN, 
           NULL); 
     if(INVALID_HANDLE_VALUE != hFile) 
      throw std::runtime_error("Failed to open file."); 

     // Fetch size 
     LARGE_INTEGER fileSize; 
     if(!GetFileSizeEx(hFile, &fileSize)); 
      throw std::runtime_error("GetFileSizeEx() failed."); 

     // Resize output buffer. 
     output.resize(fileSize.LowPart); 

     // Read the file contents. 
     ULONG bytesRead; 
     if(!ReadFile(hFile, &output[0], fileSize.LowPart, &bytesRead, NULL)) 
      throw std::runtime_error("ReadFile() failed."); 

     // Recover resources. 
     CloseHandle(hFile); 
    } 
    catch(std::exception&) 
    { 
     // Dump the error. 
     std::cout << e.what() << " GetLastError() = " << GetLastError() << std::endl; 

     // Recover resources. 
     if(INVALID_HANDLE_VALUE != hFile) 
      CloseHandle(hFile); 

     throw; 
    } 
} 
+0

我可以爲你麻煩你的一個片段嗎?不確定我完全理解 – mezamorphic

+0

請注意,如果文件非常小,則FILE_FLAG_SEQUENTIAL_SCAN可能沒有任何區別 - 它告訴緩存執行更多預讀操作,但對於小文件,正常預讀可能會讀取整個文件文件。 –

+0

@JerryCoffin - 你是對的 - 小文件(少於幾個緩存頁)通常會被全部讀取。一般來說,在這種情況下,當您瞭解文件訪問模式時,最好將這些數據提供給操作系統。 – Bukes

相關問題