我一直在想,如果线性地址转换过程遇到TLB miss,那么它会遍历内存中的页目录结构。然而,英特尔手册 Vol.3/4.10.3 定义了我以前从未听说过的所谓的分页结构缓存。
这是它为 TLB 未命中所做的:
If the processor does not find a relevant TLB entry or PDE-cache entry, it may use the upper bits of the linear address (for 4-level paging, bits 47:30; for 5-level paging, bits 56:30) to select an entry from the PDPTE cache that is associated with the current PCID. It can then use that entry to complete the translation process (locating a PDE, etc.) as if it had traversed the PDPTE, the PML4E, and (for 5-level paging) the PML5E corresponding to the PDPTE-cache entry
和
If the processor does not find a relevant TLB entry, PDE-cache entry, or PDPTE-cache entry, it may use the upper bits of the linear address (for 4-level paging, bits 47:39; for 5-level paging, bits 56:39) to select an entry from the PML4E cache that is associated with the current PCID. It can then use that entry to complete the translation process (locating a PDPTE, etc.) as if it had traversed the corresponding PML4E.
所以TLB miss并不一定意味着遍历整个页面结构。
您能否提供一些性能事件示例来描述页面结构缓存访问以及如何优化页面结构缓存的使用?
最佳答案
据我所知,Skylake 没有任何关于页面浏览细节的性能事件。有完成步行次数和事件循环次数的计数器,因此我想您可以尝试平均每次步行花费的时间。
(在 Skylake 和更高版本中有两个 PMH 页面丢失处理程序,但是 dtlb_load_misses.walk_pending
每个周期计数 1 或 2,具体取决于有多少是事件的。或者 0 表示两者都没有。但它可能只be counting for demand-load TLB misses, not next-page TLB prefetch. 存储和代码获取也有类似的事件。
其他一些事件,如 dtlb_load_misses.walk_active
会在一个或两个 page-walkers 处于事件状态时计算周期。)
利用 page walkers 缓存更高级别的页表(和/或 L2/L1d 也缓存这些物理位置)的主要方法是在更大范围内拥有局部性,例如让您的工作集中的热点页面位于相同对齐的 2M 或 1G 区域内,因此它们都共享基数树(页表)的公共(public)上部。
或在几个组内;您不需要尝试让 malloc
/mmap
在您的代码或堆栈旁边进行分配。
这主要取决于您的操作系统,除非您进行大量分配并自行分割。
静态代码/数据(至少在非 PIE Linux 可执行文件中)starts at absolute address 4MiB by default ,它位于 2M 大页面的开头,靠近 1G 大页面的开头。并且非常接近高于该水平的 2^9 G 级别的开始。因此,即使您有很多 代码 + 数据,它的位置也很好。我假设非 PIE 可执行文件的 ASLR 更细化,但与 1G 级别相比,静态代码+数据通常非常小。
关于assembly - 页面结构缓存性能事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74190235/