perf 调整内存页的大小

 

原理

TLB(Translation lookaside buffer)为页表(存放虚拟地址的页地址和物理地址的页地址的映射关系)在CPU内部的高速缓存。TLB的命中率越高,页表查询性能就越好。

TLB的一行为一个页的映射关系,也就是管理了一个页大小的内存:

TLB管理的内存大小 = TLB行数 x 内存的页大小

同一个CPU的TLB行数固定,因此内存页越大,管理的内存越大,相同业务场景下的TLB命中率就越高。

perf stat -p $PID -d -d -d
 

输出结果包含如下信息,其中1.21%和0.59%分别表示数据的miss率和指令的miss率。

1,090,788,717      dTLB-loads                #  520.592 M/sec
13,213,603      dTLB-load-misses             #    1.21% of all dTLB cache hits
669,485,765      iTLB-loads                 #  319.520 M/sec
3,979,246      iTLB-load-misses              #  0.59% of all iTLB cache hits

 

 

 

 

 

 

[root@bogon c++]# perf stat -p 3288 -d -d -d 

^C
 Performance counter stats for process id '3288':

        882.898240      task-clock (msec)         #    0.038 CPUs utilized          
             6,449      context-switches          #    0.007 M/sec                  
                44      cpu-migrations            #    0.050 K/sec                    (75.57%)
               114      page-faults               #    0.129 K/sec                    (75.57%)
     1,567,938,758      cycles                    #    1.776 GHz                      (79.14%)
     1,880,169,545      instructions              #    1.20  insn per cycle           (77.56%)
   <not supported>      branches                                                    
        13,518,084      branch-misses                                                 (86.37%)
       699,533,782      L1-dcache-loads           #  792.315 M/sec                    (89.25%)
        12,758,831      L1-dcache-load-misses     #    1.82% of all L1-dcache hits    (87.42%)
   <not supported>      LLC-loads                                                   
   <not supported>      LLC-load-misses                                             
       947,575,815      L1-icache-loads           # 1073.256 M/sec                    (88.92%)
333,236,998,181,864      L1-icache-load-misses     # 35167317.79% of all L1-icache hits  (0.00%)
   <not supported>      dTLB-loads                                                  
134,920,245,165,482      dTLB-load-misses                                              (0.00%)
   <not supported>      iTLB-loads                                                  
23,373,287,351,746      iTLB-load-misses                                              (0.00%)
   <not supported>      L1-dcache-prefetches                                        
   <not supported>      L1-dcache-prefetch-misses                                   

      23.450708972 seconds time elapsed


You have mail in /var/spool/mail/root

 

使用Hugepage大页优化程序性能

页(page)的大小和程序的性能紧密相关。

使用大页的好处:

  • 减少page table本身的内存开销
  • 减少单次page table walk所需的时间
  • 减少TLB miss的发生次数

使用大页的坏处:

    • 增加内部碎片
    • 增加单次缺页异常(page fault)的开销

 

 
#include <stdlib.h>

#define TWOMB 2097152

int main () {
    srand(1000);
    int size = TWOMB * 100;
    int *arr = malloc(size);
    for (int i = 0; i < 10000000; i++) {
        int offset = rand() % (size / sizeof(int));
        arr[offset] = rand();
    }

    return 0;
}

 

这个例子分配了很大(200mb)的内存,然后在一个循环中随机访问其中的数据。如果使用4k页,则总共需要 200mb / 4kb = 51200 个页,这个数目应该是远超过tlb所能容纳的页的数量,从而产生大量TLB miss。而使用2m大页,则TLB中只需要100个entry即可容纳所有的数据。

编译后使用

[root@bogon c++]# perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses ./huge

 Performance counter stats for './huge':

   <not supported>      dTLB-loads                                                  
        10,035,694      dTLB-load-misses                                            
   <not supported>      iTLB-loads                                                  
             7,349      iTLB-load-misses                                            

       1.879773679 seconds time elapsed

       1.849813000 seconds user
       0.029996000 seconds sys


You have mail in /var/spool/mail/root

 

然后使用libhugetlbfs将内存分配在大页上:

export LD_PRELOAD=libhugetlbfs.so
export HUGETLB_MORECORE=yes

 

然后再运行同样的perf命令,可以看到TLB miss大幅减小了:

 

posted on 2021-04-23 18:05  tycoon3  阅读(538)  评论(0编辑  收藏  举报

导航