瓶颈性能调优

文档状态:编辑....



工具可以细化探讨问题的粒度。


Table of Contents

起源

背景知识

关于处理器

Tracepoints

散落在内核源代码中的一些 hook,一旦使能,它们便可以在特定的代码被运行到时被触发,这一特性可以被各种 trace/debug 工具所使用。Perf 就是该特性的用户之一

比如说你想了解内核内存管理模块的行为,可以里用slab分配器的tracepoint hook,当然,我们可以
将hook来的数据进行分析生成报告便于诊断。所以可以方面了解程序的内部细节。

工具

perf

  You may need to install the following packages for this specific kernel:
    linux-tools-4.10.0-28-generic
    linux-cloud-tools-4.10.0-28-generic

  You may also want to install one of the following packages to keep up to date:
    linux-tools-generic
    linux-cloud-tools-generic

作用:
- 分析硬件事件(instructions retired ,processor clock cycles )
- 分析软件事件( Page Fault 和进程切换)
- 分析断点事件
- 函数级别采样
- 做 benchmark 衡量调度器的好坏
运作机制:
- 通过对软硬中断以及hook出现时候的回调产生信息,这三种情况作为三大类采样点,可以根据选用采样点的不同,来了解程序执行的各个部分在此采样点上的分布律(简单的说,采样点相当于概率论中所说的事件,通过选择对特定事件进行监测,从而得知程序的不同部分对事件触发的概率,概率和当然为1)

常用命令
1. perf list
列出所有的事件[Hardware Event],[Software Event],[Tracepoint event]
2. perf stat参考文章

#hello.c
1 #include <stdio.h>
  2 void loop(){
  3     int count=0;
  4     for(int i=0;i<20;i++)
  5         count++;
  6 }
  7 void func1(){
  8     for(int i=0;i<100;i++)
  9         loop();
 10 }
 11 void func2(){
 12     for(int i=0;i<1000;i++)
 13         loop();
 14 }
 15 int main(){
 16     func1();
 17     func2();
 18     return 0;
 19 }

meta@meta:~/workstation/c/performace$ gcc -g hello.c -o hello
meta@meta:~/workstation/c/performace$ perf stat ./hello 2&> sys.data
 Performance counter stats for './hello 2':
 0.464171      task-clock (msec)         #    0.555 CPUs utilized          
 0             context-switches          #    0.000 K/sec                  
 0             cpu-migrations            #    0.000 K/sec                  
43             page-faults               #    0.093 M/sec                  
750,271        cycles                    #    1.616 GHz                    
555,199        instructions              #    0.74  insn per cycle         
112,590        branches                  #  242.561 M/sec                  
3,717          branch-misses             #    3.30% of all branches        

       0.000836144 seconds time elapsed
/*
第一列是数据,第二列是第一列数据的单位,第三列多为以时间为量度进行统计单位时间发生的频率
几个统计值的含义分别如下():
task-clock-msecs:
cpu运算在整个任务执行过程中消耗时间的比例,该值越高,说明花费越多时间在CPU计算上而非其它(比如I/O);这里第一列数值为0.464171毫秒,而通过最后一行知道程序整个执行时间为0.000836144秒,所以百分比为0.464171 /(0.000836144×1000)=0.555,即第一行倒数第二列数值。
context-switches:记录程序在运行过程中发生的进程切换次数,应该避免频繁的进程切换;这里为0次。
CPU-migrations:  记录程序在运行过程中发生的CPU迁移次数,即被调度器从一个CPU转移到另外一个 CPU上运行;这里为0次。
page-faults:     记录程序在运行过程中发生的缺页中断次数。
cycles:          记录执行程序所发费的处理器周期数。
instructions:    记录执行程序所花费的指令数。
branches:        记录程序在运行过程中的分支指令数。
branch-misses:   记录程序在运行过程中的分支预测失败次数。
cache-references:记录程序在运行过程中的cache命中次数。
cache-misses:    记录程序在运行过程中的cache失效次数。
*/
meta@meta:~/workstation/c/performace$ perf stat -r n(次数) ./hello 2&> sys.data

perf record -e raw_syscalls:sys_enter ls
/*上述命令可以进行平均统计*/
  1. perf top
用过top的人都熟悉,这个命令可以根据三大类事件发生的频率进行排名你可以使用-e指定事件,至于事件选择哪个,可以通过`perf list`列出

meta@meta:~/workstation/c/performace$ sudo perf top -e cache-misses
PerfTop:88 irqs/sec kernel:64.8% exact:0.0% [3000Hz cache-misses],(all, 4 CPUs)
-------------------------------------------------------------------------------

    18.35%  perf                [.] 0x0000000000099837
     5.28%  libpthread-2.23.so  [.] __pthread_rwlock_rdlock
     4.58%  perf                [.] 0x00000000000a5441
     4.56%  perf                [.] 0x00000000000a5446
     2.55%  perf                [.] 0x00000000000992d3
     2.07%  [kernel]            [k] __bpf_prog_run
     1.67%  [kernel]            [k] clear_page_c_e
     1.49%  chromium-browser    [.] 0x000000000479b2b1
     1.45%  perf                [.] 0x00000000000bef81
     1.42%  [kernel]            [k] update_cfs_rq_load_avg.constprop.90
     1.32%  perf-25620.map      [.] 0x00002bba5db0bf60
     1.30%  libc-2.23.so        [.] __strchr_sse2
     1.16%  perf-7458.map       [.] 0x000016d9891b703f
     1.16%  chromium-browser    [.] 0x0000000002860517
     1.12%  [kernel]            [k] sys_futex
     1.07%  [kernel]            [k] filemap_map_pages
     1.07%  chromium-browser    [.] 0x0000000004957b80
     1.04%  [kernel]            [k] __switch_to
  1. perf record
/*上述的命令已经很不错了,但是列出的只是针对程序在硬件内核中某些事件执行的频率,针对程序进行分析时,我们要考虑单个函数级别在事件上的频率分布,perf可以进行函数级别查看*/
meta@meta:~/workstation/c/performace$ sudo perf record -e cpu-clock ./hello
meta@meta:~/workstation/c/performace$ sudo perf report
/*出错!can not open tips.txt
检查一下*/
meta@meta:~/workstation/c/performace$ sudo strace -f -e file perf report 2>&1 | grep tips.txt
access("/usr/share/doc/perf-tip/tips.txt", F_OK) = -1 ENOENT (No such file or directory)
access("/build/linux-hwe-vH8Hlo/linux-hwe-4.10.0/debian/build/tools-perarch/tools/perf/Documentation/tips.txt", F_OK) = -1 ENOENT (No such file or directory)
# (Cannot load tips.txt file, please install perf!)

/*bug:没解决这个问题*/

meta@meta:~/workstation/c/performace$ sudo perf record e cpu-clock g ./hello
-g选项可以显示调用栈
  1. perf probe schedule:12 cpu
meta@meta:~/workstation/c/performace$ perf probe schedule:12 cpu 
meta@meta:~/workstation/c/performace$ perf record -f -e probe:schedule -a sleep 1 
/*上例利用 probe 命令在内核函数 schedule() 的第 12 行处加入了一个动态 probe 点,和 tracepoint 的功能一样,内核一旦运行到该 probe 点时,便会通知 perf。可以理解为动态增加了一个新的 tracepoint。*/
  1. Perf sched
  2. perf bench
  3. perf lock
  4. perf Kmem
  5. perf timechart
  6. firegraph
    参照perf2
    Instance
  7. 针对branch-misses进行优化为什么有序数组在循环中速度比无序的快

这里还是有点乱,不知道下面是否是从IO角度考虑进行优化.

swap

# adjust swap
Linux提供了一个/proc/sys/vm/swappiness,只需要简单的echo 0-100 中的一个数值到这个文件中即可。值越大,系统swap到硬盘的越多.

网上看到一个2.6内核维护者,将它设置成 100。给出的理由:“我的观点是降低kernel swap出内存数据不对。你实际上不想让几百兆的内存在自己的机器内存中呆着,但从未被访问。所以把这些数据请到磁盘上,留出更多的主存给要用的程序”.

page size

# include <unistd.h>
int getpagesize();//get size of page