处理TLB缺失

4
我想查看我的程序正在访问哪些页面。现在一种方法是使用mprotectSIGSEGV处理程序来记录正在访问的页面。然而,这涉及设置我感兴趣的所有内存页面的保护位的开销。
第二种方法是在开始时失效翻译后备缓冲区(TLB),然后记录缺失。每次缺失时,我都会记录寻址的内存页面,并因此记录下它。现在问题是如何在Linux程序的用户空间中处理TLB缺失。
如果您知道比TLB缺失或mprotect更快的方法来记录脏内存页面,请告诉我。另外,我需要x86的解决方案。
3个回答

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和许多其他流行平台上,无论是在用户空间还是内核空间,您都无法处理缺失。这是因为大多数平台在硬件中管理TLB缺失。MMU(CPU /芯片组的一部分)将在页表上进行漫游,并会透明地获取物理地址。 仅当设置了某些位或地址区域未映射时,才会生成页面故障中断并传递给内核。

此外,现代CPU似乎没有办法转储TLB(但386DX能够做到

您可以通过引入延迟来尝试检测TLB缺失。但是,这种延迟可能被TLB查找的乱序开始隐藏。

此外,大多数硬件事件(内存访问、TLB 访问、TLB 命中和 TLB 未命中)都是由硬件性能监测器计数的(CPU 的这一部分被 Vtune、CodeAnalyst 和 oprofile 使用)。不幸的是,这些事件只有全局计数器,并且不能同时激活超过 2-4 个事件。好消息是,您可以将 perfmon 计数器设置为在达到某个计数时中断。然后,您将通过中断获得指令地址($eip),在该地址处达到了计数。因此,您可以使用此硬件查找 TLB 未命中热点(它存在于每个现代 x86 CPU 中;包括 Intel 和 AMD)。

6

TLB 对用户空间程序透明,最多只能通过某些性能计数器(不包含地址)来计算 TLB 非命中。


或者,使用性能计数器进行采样。它不会显示内存地址,但会指出程序代码中的TLB热点位置。 - osgx
这是不正确的,你可以使用许多PMU支持的芯片来计算TLB缺失。 - Rev316

-1

查看您的进程的/proc/PID/maps文件。根据http://www.kernel.org/doc/Documentation/filesystems/proc.txt中的文档,/proc/PID/maps指定了每个进程的内存映射。此映射将告诉您“我的程序正在访问哪些页面”。但是,看起来您想知道其中哪些是脏页面。虽然我不确定如何找到确切的脏页面列表,但可以通过查看/proc/PID/smaps中的私有脏和共享脏字段并将其除以页面大小来找到多少页面是脏的。请注意,此方法非常快速。我相信可以通过定期轮询/proc/PID/maps来获取哪些页面是脏的大致想法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接