c - 每个 mmap/access/munmap 两次 TLB 未命中

标签 c performance performancecounter perf tlb

for (int i = 0; i < 100000; ++i) {
    int *page = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
                            MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);

    page[0] = 0;

    munmap(page, PAGE_SIZE);
}

我希望在用户空间中获得约 100000 个 dTLB 存储未命中,每次迭代一个(还有约 100000 个页面错误和内核的 dTLB 加载未命中)。运行以下命令,结果大约是我预期的 2 倍。如果有人能澄清为什么会这样,我将不胜感激:

perf stat -e dTLB-store-misses:u ./test
Performance counter stats for './test':

           200,114      dTLB-store-misses

       0.213379649 seconds time elapsed

附言我已经验证并确定生成的代码不会引入任何可以证明此结果合理的内容。此外,我确实遇到了 ~100000 个页面错误和 dTLB-load-misses:k。

最佳答案

I expect to get ~100000 dTLB-store-misses in userspace, one per each iteration

我希望:

  • CPU 尝试执行 page[0] = 0;,尝试加载包含 page[0] 的缓存行,找不到它的 TLB 条目,递增 dTLB-load-misses,获取翻译,意识到页面“不存在”,然后生成页面错误。
  • 页面错误处理程序分配一个页面并(因为页表被修改)确保 TLB 条目无效(可能依赖于 Intel CPU 无论如何都不会缓存“不存在”页面的事实,不一定是明确的执行 INVLPG)。页面错误处理程序返回导致错误的指令,以便重试。
  • CPU 第二次尝试执行 page[0] = 0;,尝试加载包含 page[0] 的缓存行,找不到 TLB它的条目,递增 dTLB-load-misses,获取翻译,然后修改缓存行。

为了好玩,您可以使用 MAP_POPULATE 标志和 mmap() 来尝试让内核预分配页面(并避免页面错误和第一次 TLB 未命中)。

关于c - 每个 mmap/access/munmap 两次 TLB 未命中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48552362/

相关文章:

Javascript toLowerCase() 性能与变量创建

php - Perl 与 PHP 的网络抓取

WPF 性能 : Displaying thousands of Paths/Shapes on a Canvas

assembly - 为什么执行的 AVX 指令数量会随着处理器系列的不同而变化

交叉编译。设置搜索库的最后位置

c - 如果在 C 中为 null,检查大量数据的最快方法?

c - 需要编辑哪些文件才能将新用户添加到 ubuntu?

c - 在 C 中解析文件中的指令的简单方法?

c# - 性能计数器 - System.InvalidOperationException : Category does not exist

c# - 为性能计数器分配一个浮点值