处理TLB未命中

时间:2011-09-23 13:34:59

标签: c linux caching x86 tlb

我想查看我的程序正在访问哪些页面。现在,一种方法是使用mprotectSIGSEGV处理程序来记下正在访问的页面。但是,这涉及为我感兴趣的所有存储器页面设置保护位的开销。

第二种方法是在开始时使翻译后备缓冲区(TLB)无效,然后记下未命中。每次未命中时,我都会记下寻址的内存页面,因此请记下来。现在的问题是如何处理Linux程序的用户空间中的TLB未命中。

如果您知道甚至比TLB未命中或 mprotect 更快的方法来记下脏的内存页面,请告诉我。另外,我只想要一个x86的解决方案。

3 个答案:

答案 0 :(得分:7)

  

我想查看我的程序正在访问哪些页面。

您可以模拟CPU并获取此数据。变体:

  • 1)valgrind - 用户空间二进制文件的动态翻译器,具有良好的仪器支持。尝试使用cachegrind工具 - 它甚至可以模拟L1 / L2缓存;您也可以尝试构建新工具来记录所有内存访问(例如,使用页面粒度)
  • 2)qemu - 动态转换器,包括系统范围和进程范围的模式。我所知道的原始qemu中没有任何仪器
  • 3)bochs - 系统范围的CPU仿真器(非常慢)。您可以轻松破解“内存访问”代码以获取内存日志。
  • 4)PTLsim - www.ptlsim.org/papers/PTLsim-ISPASS-2007.pdf
  

但是,这涉及为所有存储器页设置保护位的开销

这个开销太大了吗?

  

现在的问题是如何处理Linux程序的用户空间中的TLB未命中。

你无法在内核空间(在x86和许多其他流行的平台上)处理未命中或用户空间。这是因为大多数平台manages TLB misses in hardware:。 MMU(CPU /芯片组的一部分)将在页表上执行操作,并将透明地获取物理地址。 仅当设置了某些位或未映射地址区域时,才会生成页面错误中断并将其传送到内核。

此外,似乎无法在现代CPU(but 386DX was able to to this

中转储TLB

您可以尝试通过引入的延迟来检测TLB未命中。但是这种延迟可以通过TLB查找的无序启动来隐藏。

此外,大多数硬件事件(内存访问,tlb访问,tlb命中,tlb未命中)都由硬件性能监控计算(这部分CPU由Vtune,CodeAnalyst和oprofile使用)。不幸的是,这只是事件的全局计数器,您不能同时激活2-4个以上的事件。好消息是,当达到一些计数时,你可以将perfmon计数器设置为中断。然后,您将获得(通过中断)指令的地址($ eip),其中已达到计数。所以,你可以找到这个硬件的TLB-miss-heavy热点(它在每个现代的x86 cpu中;无论是intel还是amd)。

答案 1 :(得分:6)

TLB对用户空间程序是透明的,最多可以通过一些性能计数器(没有地址)来计算TLB未命中数。

答案 2 :(得分:-1)

查看/ proc / PID / maps文件以查找您的进程。根据{{​​3}}中的文档,/ proc / PID / maps指定每个进程的内存映射。此地图将告诉您“我的程序正在访问哪些页面”。但是,看起来您想知道哪些是脏页。虽然我不确定如何找到脏页的确切页面,但通过查看私有脏域和共享脏域,可以找到有多少页面是脏的/ proc / PID / smaps并将其除以pagesize。请注意,此方法非常快。我相信通过定期轮询/ proc / PID / map可以获得哪些页面是脏的近似概念。