c++ - 如何优化C++二进制文件读取?

标签 c++ file optimization input

我有一个复杂的解释器从(有时)多个文件中读取命令(确切的细节超出了范围),但它需要多次迭代这些多个文件(有些文件的大小可能是 GB,防止良好的缓冲)。

我希望提高从文件中读取每个命令的速度。

我已经使用 RDTSC(程序计数器)寄存器对代码进行了微基准测试,足以了解大约 80% 的时间花在从文件读取上。

事情是这样的:生成输入文件的程序实际上比在我的小型解释器中读取文件要快。即,我可以(理论上)将数据生成器链接到解释器并跳过文件,而不是输出文件,但这应该不会更快,对吧?

我做错了什么?或者写入是否比从文件中读取快 2 到 3 倍(至少)?

我考虑过 mmap 但 http://lemire.me/blog/archives/2012/06/26/which-is-fastest-read-fread-ifstream-or-mmap/ 上的一些结果似乎表明它并不比 ifstream 快。或者 mmap 在这种情况下会有帮助吗?

详情:

我(到目前为止)已经尝试添加缓冲区、调整参数、删除 ifstream 缓冲区(在我的测试用例中,速度减慢了 6 倍),在四处搜索后,我目前不知所措。

代码的重要部分如下。它执行以下操作:

  1. 如果数据留在缓冲区中,则将表单缓冲区复制到内存块(然后在其中使用)
  2. 如果缓冲区中没有剩余数据,请检查文件中剩余多少数据,如果超过缓冲区的大小,则复制缓冲区大小的 block
  3. 如果小于文件

    //if data in buffer
    if(leftInBuffer[activefile] > 0)
    {
        //cout <<bufferloc[activefile] <<"\n";
        memcpy(memblock,(buffer[activefile])+bufferloc[activefile],16);
        bufferloc[activefile]+=16;
        leftInBuffer[activefile]-=16;
    }
    else //buffers blank
    {
        //read in block
    
        long blockleft =  (cfilemax -cfileplace) / 16 ;
        int read=0;
    
    /* slow block starts here */
    
        if(blockleft >= MAXBUFELEMENTS)
        {
            currentFile->read((char *)(&(buffer[activefile][0])),16*MAXBUFELEMENTS);
            leftInBuffer[activefile] = 16*MAXBUFELEMENTS;
            bufferloc[activefile]=0;
            read =16*MAXBUFELEMENTS;
        }
        else //read in part of the block
        {
            currentFile->read((char *)(&(buffer[activefile][0])),16*(blockleft));
            leftInBuffer[activefile] = 16*blockleft;
            bufferloc[activefile]=0;
            read =16*blockleft;
        }
    
     /* slow block ends here */
    
        memcpy(memblock,(buffer[activefile])+bufferloc[activefile],16);
        bufferloc[activefile]+=16;
        leftInBuffer[activefile]-=16;
    }
    

编辑:这是在 Mac、osx 10.9.5、i7 和 SSD 上

解决方案:

正如下面所建议的,mmap 能够将速度提高大约 10 倍。

(对于搜索此内容的其他人) 具体打开方式为:

uint8_t * openMMap(string name, long & size)
{
int m_fd;
struct stat statbuf;
uint8_t * m_ptr_begin;

if ((m_fd = open(name.c_str(), O_RDONLY)) < 0)
{
    perror("can't open file for reading");
}

if (fstat(m_fd, &statbuf) < 0)
{
    perror("fstat in openMMap failed");
}

if ((m_ptr_begin = (uint8_t *)mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED,  m_fd, 0)) == MAP_FAILED)
{
    perror("mmap in openMMap failed");
}

uint8_t * m_ptr = m_ptr_begin;
size = statbuf.st_size;

return m_ptr;

}

阅读者:

    uint8_t *  mmfile = openMMap("my_file", length);        

    uint32_t * memblockmm;
    memblockmm = (uint32_t *)mmfile; //cast file to uint32 array
    uint32_t data = memblockmm[0]; //take int
    mmfile +=4; //increment by 4 as I read a 32 bit entry and each entry in mmfile is 8 bits.

最佳答案

这应该是一条评论,但我没有 50 声望来发表评论。

MAXBUFELEMENTS 的值是多少?根据我的经验,许多较小的读取比一次较大的读取要慢得多。我建议如果可能的话读取整个文件,有些文件可能是 GB,但即使一次读取 100MB 也比读取 1 MB 读取 100 次要好。

如果这还不够好,您可以尝试的下一步是压缩(zlib)输入文件(由于大小可能必须将它们分成 block ),然后在内存中解压缩它们。此方法通常比读取未压缩文件更快。

关于c++ - 如何优化C++二进制文件读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28484573/

相关文章:

java - 我的 Java 程序出现 FileSystemException 错误

c# - 我可以给编译器/JIT 什么优化提示?

c++ - 在纯 C++ (C++11) 中扩充一个类/应用一个方面

c++ - 为什么在模板化 lambda 时编译器生成的代码不同?

javascript - 如何使用 javascript(无 jQuery) chop 文件?

复制文本文件的内容并将其复制到另一个文件

mysql - 优化 MySql InnoDB 数据库中的慢速查询

optimization - Deflate 压缩浏览器兼容性以及相对于 GZIP 的优势

java - 运行期间非阻塞输入流

C++ 宏,将 n 扩展为 1, 2, 3, ... n