我想查看我的程序正在访问哪些页面。
您可以模拟 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-miss-heavy 热点(它存在于每个现代 x86 cpu;intel 和 amd 中)。