如何在 C++ 中正确进行页表预热?

W1n*_*003 6 c++ paging caching shared-memory

我在两个进程之间分配了很大的共享内存(4 MB)。我的 process-1 在此内存池上进行写入,将其用作循环缓冲区,通过逐个写入 256 字节的块。我的 process-2 从内存中读取。我正在使用锁进行同步。我正在测量写入时间,每执行 16 次操作就会出现峰值。我的猜测是,这是因为访问新页面(因为 16*256 字节 = 4096 字节)。

由于这种情况发生在程序的关键点并导致高延迟,因此我决定在构造函数分配/绑定到共享内存后通过访问此内存池来预热 process-1 的页表。

//global var
dummy_byte = 0;

for (int i=0; i<16*1024; i++)
{
    dummy_byte ^= buffer[i*256]; 
}
Run Code Online (Sandbox Code Playgroud)

目标是访问每个块中的一个字节,以便获取所有页面。我为此使用全局变量,否则编译器会优化并删除我的循环(因为没有人读取保存的值)。我后来使用 objdump 验证了这段代码没有被删除。

我面临的问题是延迟峰值仍在发生。在玩预热逻辑时,我尝试了以下方法:

for (int i=0; i<16*1024; i++)
{
    buffer[i*256] = 0;
}
Run Code Online (Sandbox Code Playgroud)

我发现这不会导致临界点出现延迟峰值。问题是我不想将垃圾写入缓冲区,因为那里可能存在一些有用的东西,并且对同一字节进行读写会导致竞争条件,因为另一个进程可能正在从共享内存中读取。

我想知道:

  1. 这确实是因为 tlb 才发生的吗?或者是其他东西?
  2. 如果是tlb,为什么read无法预热页面,而write却可以?
  3. 还有什么可以尝试的吗?