为什么将 rg(ripgrep) 与 mmap 一起使用会触发更多次要页面错误?

Why using rg(ripgrep) with mmap triggers more minor page faults?

提问人:Steve Wu 提问时间:10/15/2023 最后编辑:Peter CordesSteve Wu 更新时间:10/15/2023 访问量:29

问:

我使用 rg + perf 来衡量 mmap 性能与 pread,用作性能指标。结果如下:minor page fault

mmap

perf stat -e major-faults,minor-faults  rg -j1 -F 123 a-big-file --mmap
             0      major-faults
           509      minor-faults

   0.002241400 seconds time elapsed

   0.000000000 seconds user
   0.002221000 seconds sys

无 MMAP

perf stat -e major-faults,minor-faults  rg -j1 -F 123 a-big-file --no-mmap
             0      major-faults
           396      minor-faults

   0.002911774 seconds time elapsed

   0.002890000 seconds user
   0.000000000 seconds sys

grep 针对空文件

性能计数器统计信息:rg -j1 -F 123 empty_file --mmap

             0      major-faults
           393      minor-faults

   0.001652534 seconds time elapsed

   0.000000000 seconds user
   0.001648000 seconds sys

似乎使用 mmap 会导致更多的页面错误,有没有人知道如何对 Linux 进行深度跟踪,以便可以显示导致轻微页面错误的代码?目前我的怀疑是munmap。

Linux 调试 性能 页面错误

评论


答:

0赞 Peter Cordes 10/15/2023 #1

当您第一次触摸 mmaped 区域时,使用读取大文件通常涉及软(次要)页面错误,除非您使用(如果 pagecache 中尚未热,它也会等待 I/O,因此大多数程序不希望这样做。mmapMAP_POPULATE

故障(当一个页面出现故障时,将相邻页面连接到页表中)使故障成本通常不会太差。内核应该注意到页面错误中的顺序读取模式,并连接多个页面,而不仅仅是出错的页面。

madvise(MADV_SEQUENTIAL)可能会有所帮助,或者可能只对磁盘的 I/O 有所帮助。从另一个线程执行操作可能是个好主意;IDK 我没有测试过。 在初始 mmap 上,它的缺点是不允许 mmap 返回,因此您甚至无法开始读取文件,并且无法将计算与 I/O 重叠。但是,让内核检查页面并将它们连接到页表中,同时执行您正在执行的任何操作可能会有所帮助。MADV_POPULATE_READMAP_POPULATE


perf record -e page-faults应该能够记录故障指令。由于您的程序不会触发任何主要的页面错误(必须休眠以进行 I/O,因为您的大文件不会太大以至于内核无法将其保持在页面缓存中),因此唯一的页面错误将是次要错误。

(我没有对此进行测试,并且 IDK 事件的默认样本粒度是多少;IDK,如果它默认会记录每个页面错误的样本。page-faults