【内存】TLB缓存是个神马鬼,如何查看TLB miss?
目录
原文:https://blog.csdn.net/zhangyanfei01/article/details/100053533
Linux在v2.6.11以后,最终采用的方案是4级页表,分别是:
- PGD:page Global directory(47-39), 页全局目录
- PUD:Page Upper Directory(38-30),页上级目录
- PMD:page middle directory(29-21),页中间目录
- PTE:page table entry(20-12),页表项
这样,一个64位的虚拟空间,就需要:2^9 个PGD + 2^9 个PUD + 2^9 个PMD + 2^9 个PTE = 2048个页表数据结构。现在的页表数据结构被扩展到了8byte。仅仅需要(2048*8=)16K就可以支持起(2^48 =)256T的进程地址空间。
页表带来的问题
处理器引入MMU后,读取指令、数据需要访问两次内存:
首先通过查询页表得到物理地址,然后访问该物理地址读取指令、数据。
既由于页表存放在主存中,因此程序每次访存至少需要两次(单级页表):一次访存获取物理地址,第二次访存才获得数据。
虽然16K的页表数据支持起了256T的地址空间寻址。但是,这也带来了额外的问题,页表是存在内存里的。那就是一次内存IO光是虚拟地址到物理地址的转换就要去内存查4次页表(4级),再算上真正的内存访问,竟然需要5次内存IO才能获取一个内存数据!!
TLB应运而生
为了减少因为MMU导致的处理器性能下降,引入了TLB,TLB是Translation Lookaside Buffer的简称,可翻译为“地址转换后援缓冲器”,也可简称为“快表”。
简单地说,TLB就是页表的Cache,其中存储了当前最可能被访问到的页表项,其内容是部分页表项的一个副本。只有在TLB无法完成地址翻译任务时,才会到内存中查询页表,这样就减少了页表查询导致的处理器性能下降。
TLB原理
当cpu要访问一个虚拟地址/线性地址时,CPU会首先根据虚拟地址的高20位(20是x86特定的,不同架构有不同的值)在TLB中查找。如果是表中没有相应的表项,称为TLB miss,需要通过访问慢速RAM中的页表计算出相应的物理地址。同时,物理地址被存放在一个TLB表项中,以后对同一线性地址的访问,直接从TLB表项中获取物理地址即可,称为TLB hit。
归纳如下:
- 1.CPU产生一个虚拟地址
- 2.MMU从TLB中获取页表,翻译成物理地址
- 3.MMU把物理地址发送给L1/L2/L3/内存
- 4.L1/L2/L3/内存将地址对应数据返回给CPU
由于第2步是类似于寄存器的访问速度,所以如果TLB能命中,则虚拟地址到物理地址的时间开销几乎可以忽略。如果想了解TLB更详细的工作机制,请参考《深入理解计算机系统-第9章虚拟内存》
想像一下x86_32架构下没有TLB的存在时的情况,对线性地址的访问,首先从PGD中获取PTE(第一次内存访问),在PTE中获取页框地址(第二次内存访问),最后访问物理地址,总共需要3次RAM的访问。如果有TLB存在,并且TLB hit,那么只需要一次RAM访问即可。
如何查看TLB miss
既然TLB缓存命中很重要,那么有什么工具能够查看你的系统里的命中率呢? 还真有
# perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses -p $PID
Performance counter stats for process id '21047':
627,809 dTLB-loads
8,566 dTLB-load-misses # 1.36% of all dTLB cache hits
2,001,294 iTLB-loads
3,826 iTLB-load-misses # 0.19% of all iTLB cache hits
iTLB-loads可大于也可小于iTLB-load-misses:https://stackoverflow.com/questions/49933319/how-to-interpret-perf-itlb-loads-itlb-load-misses
On your Broadwell processor, perf maps iTLB-loads to ITLB_MISSES.STLB_HIT, which represents the event of a TLB lookup that misses the L1 ITLB but hits the unified TLB for all page sizes, and iTLB-load-misses to ITLB_MISSES.MISS_CAUSES_A_WALK, which represents the event of a TLB lookup that misses both the L1 ITLB and the unified TLB (causing a page walk) for all page sizes. Therefore, iTLB-load-misses can be larger or smaller than or equal to iTLB-loads. They are independent events.
iTLB和 dTLB含义:https://zhengheng.me/2015/11/12/perf-stat/
https://blog.csdn.net/u011630575/article/details/66476165
扩展
因为TLB并不是很大,只有4k,而且现在逻辑核又造成会有两个进程来共享。所以可能会有cache miss的情况出现。而且一旦TLB miss造成的后果可比物理地址cache miss后果要严重一些,最多可能需要进行5次内存IO才行。建议你先用上面的perf工具查看一下你的程序的TLB的miss情况,如果确实不命中率很高,那么Linux允许你使用大内存页,很多大牛包括PHP7作者鸟哥也这样建议。这样将会大大减少页表项的数量,所以自然也会降低TLB cache miss率。所要承担的代价就是会造成一定程度的内存浪费。在Linux里,大内存页默认是不开启的。
参考文献
perf 统计 内存相关event (https://blog.csdn.net/mrpre/article/details/83537311)
perf 可探测 的所有 event ,均可以使用命令perf list获得。
本文举几个和内存相关的性能的几个event例子
探测 进程 的缺页中断数(page fault)
perf stat -e faults ./mem
能够统计 ./mem 执行 周期内,引发的 缺页中断数。
Performance counter stats for './mem':
100,126 faults
0.203315268 seconds time elapsed
探测正在运行的进程,则使用
perf stat -e faults -p $PID运行,命令掐断后,打印出命令开始到命令结束时,目标进程的缺页中断数。
可以 使用 perf record来探测 指定 event 的热点函数,例如
perf record -e faults ./mem
使用
perf report
输出结果。
Samples: 655 of event 'faults', Event count (approx.): 100151
Overhead Command Shared Object Symbol
99.57% mem mem [.] func
0.35% mem ld-2.17.so [.] _dl_lookup_symbol_x
0.06% mem ld-2.17.so [.] _dl_important_hwcaps
0.01% mem ld-2.17.so [.] _dl_start
0.00% mem ld-2.17.so [.] _start
0.00% mem [kernel.vmlinux] [k] __clear_user
0.00% mem [kernel.vmlinux] [k] copy_user_enhanced_fast_string
原理
在内核缺页中断处,有perf的钩子,用于统计缺页中断的次数:
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
内核源码中搜索 PERF_COUNT_SW_PAGE_FAULTS即可。
探测 进程 TLB相关event
perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses,L1-icache-load-misses ./mem
或者指定进程id进行探测
perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses,L1-icache-load-misses -p $PID
$perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses,L1-icache-load-misses ./mem
Performance counter stats for './mem':
89,946,326 dTLB-loads (80.09%)
17,030 dTLB-load-misses # 0.02% of all dTLB cache hits (40.47%)
10 iTLB-loads (39.96%)
137 iTLB-load-misses # 1370.00% of all iTLB cache hits (59.80%)
98,113 L1-icache-load-misses (79.65%)
0.201743107 seconds time elapsed
因为是 硬件event,所以不同的CPU架构,这些值代表的不一样。一样的是,dTLB代表了数据的TLB统计,iTLB代表的是指令的TLB统计。
相关 参考文档:http://web.eece.maine.edu/~vweaver/projects/perf_events/perf_event_open.html
————————————————
版权声明:本文为CSDN博主「Mrpre」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mrpre/article/details/83537311