C++ 比boost::file\u映射读取文件更快的方法?

C++ 比boost::file\u映射读取文件更快的方法?,c++,windows,file,memory,io,C++,Windows,File,Memory,Io,我正在编写一个对延迟敏感的应用程序,它在初始化时读取文本文件。我已经分析并重新编写了我的所有算法,使85%的执行时间来自以下行: boost::interprocess::file_mapping file(Path, read_only); boost::interprocess::mapped_region data(file, read_only); 我在windows上写这篇文章-有没有更快的方法将文件映射到内存中?可移植性不是一个问题。您可以只使用Win32的本机功能,但我认为您不会

我正在编写一个对延迟敏感的应用程序,它在初始化时读取文本文件。我已经分析并重新编写了我的所有算法,使85%的执行时间来自以下行:

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

我在windows上写这篇文章-有没有更快的方法将文件映射到内存中?可移植性不是一个问题。

您可以只使用Win32的本机功能,但我认为您不会节省很多,因为boost不会增加很多开销:

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...
  }

您可以只使用Win32的本机函数,但我认为您不会节省很多,因为boost不会增加很多开销:

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...
  }

我建议放弃文件映射的想法


FM是一个复杂的结构,会增加一些开销。普通缓存读取还涉及与物理设备的非平凡交互。你可以做无缓冲阅读。可能接下来要问的是您实际需要什么类型的IO—文件有多大?它是连续的吗?它在网络上吗?您有硬件选择吗,还是在客户的机器上?

我建议放弃文件映射的想法


FM是一个复杂的结构,会增加一些开销。普通缓存读取还涉及与物理设备的非平凡交互。你可以做无缓冲阅读。可能接下来要问的是您实际需要什么类型的IO—文件有多大?它是连续的吗?它在网络上吗?您可以选择硬件,还是在客户的机器上?

如果文件很小,只需打开并使用标准Win32 CreateFile()/ReadFile()API将其读入内存即可

如果您正在按顺序使用每个文件(或者可以按这样的方式排列代码),则应该指定文件\u标志\u顺序\u扫描。这是一个提示,提示文件/缓存子系统提前读取。对于小文件,可能会在发出对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;
    }
}
void ReadFileIntoBuffer(const std::wstring和fileName,std::vector和输出)
{
句柄文件(无效的句柄值);
尝试
{
//打开文件。
hFile=CreateFile(filename.c_str(),
泛读,
文件共享读取,
无效的
开放式,
文件\u标志\u顺序\u扫描,
无效);
if(无效的句柄值!=hFile)
抛出std::runtime_错误(“打开文件失败”);
//取数大小
大整数文件大小;
如果(!GetFileSizeEx(hFile,&fileSize));
抛出std::runtime_错误(“GetFileSizeEx()失败”);
//调整输出缓冲区的大小。
调整大小(fileSize.LowPart);
//读取文件内容。
乌隆比特斯雷德;
if(!ReadFile(hFile,&output[0],fileSize.LowPart,&bytesRead,NULL))
抛出std::runtime_错误(“ReadFile()失败”);
//恢复资源。
闭合手柄(hFile);
}
捕获(标准::异常&)
{
//转储错误。

如果文件很小,只需打开并使用标准Win32 CreateFile()/ReadFile()API将其读入内存即可

如果您正在按顺序使用每个文件(或者可以按这样的方式排列代码),则应指定文件\u标志\u顺序\u扫描。这是一个提示,提示文件/缓存子系统提前积极读取。对于小文件,可能会在发出对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;
    }
}
void ReadFileIntoBuffer(const std::wstring和fileName,std::vector和输出)
{
句柄文件(无效的句柄值);
尝试
{
//打开文件。
hFile=CreateFile(filename.c_str(),
泛读,
文件共享读取,
无效的
开放式,
文件\u标志\u顺序\u扫描,
无效);
if(无效的句柄值!=hFile)
抛出std::runtime_错误(“打开文件失败”);
//取数大小
大整数文件大小;
如果(!GetFileSizeEx(hFile,&fileSize));
抛出std::runtime_错误(“GetFileSizeEx()失败”);
//调整输出缓冲区的大小。
调整大小(fileSize.LowPart);
//读取文件内容。
乌隆比特斯雷德;
if(!ReadFile(hFile,&output[0],fileSize.LowPart,&bytesRead,NULL))
抛出std::runtime_错误(“ReadFile()失败”);
//恢复资源。
闭合手柄(hFile);
}
捕获(标准::异常&)
{
//转储错误。

std::请记住,磁盘I/O比内存I/O慢多个数量级。请记住,磁盘I/O比内存I/O慢多个数量级。不仅如此,如果OP广泛使用boost,他还必须编写boost已经实现的所有样板代码,以将基于boost的代码与其winapi数据进行接口加载例程。不仅如此,如果OP广泛使用boost,他将必须编写boost已经实现的所有样板代码,以将基于boost的代码与其winapi数据加载例程连接起来。这些文件很小,这就是我将它们读入内存的原因。你能给出一个无缓冲方法的示例吗?我只是不知道如果文件很小,就有更多的理由避免映射到内存。请参阅CreateFile文档和无缓冲标志部分。Th