2012-12-16 47 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

相关问题