【内存】TLB缓存是个神马鬼,如何查看TLB miss?

目录

页表带来的问题

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导致的处理器性能下降,引入了TLBTLB是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

posted on 2022-10-04 01:24  bdy  阅读(112)  评论(0编辑  收藏  举报

导航