连续调用mmap,有缓存吗?

Cha*_*ian 3 c++ linux memory mmap

我读入向量如下:

int readBytes(string filename, vector<uint32_t> &v)
{
    // fstat file, get filesize, etc.

    uint32_t *filebuf = (uint32_t*)mmap(0,filesize,PROT_READ,
                                        MAP_FILE|MAP_PRIVATE,
                                        fhand,0);
    v = std::vector<uint32_t>(filebuf,filebuf+numrecords);
    munmap(filebuf, filesize);
}
Run Code Online (Sandbox Code Playgroud)

在 main() 中我有两个连续的调用(纯粹作为测试):

vector<uint32_t> v(10000);    
readBytes(filename, v);
readBytes(filename, v);
// ...
Run Code Online (Sandbox Code Playgroud)

第二个调用几乎总是给出更快的时钟时间:

Profile time [1st call]: 0.000214141 sec
Profile time [2nd call]: 0.000094109 sec
Run Code Online (Sandbox Code Playgroud)

查看系统调用表明内存块不同:

mmap(NULL, 40000, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fe843ac8000
mmap(NULL, 40000, PROT_READ, MAP_PRIVATE, 4, 0) = 0x7fe843ac7000
Run Code Online (Sandbox Code Playgroud)

为什么第二个调用更快?巧合?如果有的话,会缓存什么?

Use*_*ess 5

假设您正在谈论一些*NIX-ish 的东西,可能有一个页面缓存,其工作正是缓存此类数据以获得加速。除非在从缓存中逐出这些页面的调用之间出现其他情况,否则它们仍然会在那里。

因此,第一个调用可能必须:

  1. 分配页面
  2. 将页面映射到进程地址空间
  3. 将这些页面中的数据复制到向量中(可能会导致磁盘中的数据出现故障)

第二次调用可能会发现页面仍在缓存中,并且只需:

  1. 将页面映射到进程地址空间
  2. 将这些页面中的数据复制到向量中(这次它们已预先出现故障,因此这是一个简单的内存操作)

事实上,我跳过了一个步骤:您评论中的 open/fstat 步骤可能通过 inode 缓存加速。