perf-应用程序的调优与使用

20 篇文章 0 订阅

  
    Perf 是用来进行软件性能分析的工具。    通过它,应用程序可以利用 PMU,tracepoint 和内核中的特殊计数器来进行性能统计。它不但可以分析指定应用程序的性能问题 (per thread),也可以用来分析内核的性能问题,当然也可以同时分析应用代码和内核,从而全面理解应用程序中的性能瓶颈。
    使用 perf,您可以分析程序运行期间发生的硬件事件,比如 instructions retired ,processor clock cycles 等;您也可以分析
软件事件,比如 Page Fault 和进程切换。
    这使得 Perf 拥有了众多的性能分析能力,举例来说,使用 Perf 可以计算每个时钟周期内的指令数,称为 IPC,IPC 偏低表明代码没有很好地利用 CPU。Perf 还可以对程序进行函数级别的采样,从而了解程序的性能瓶颈究竟在哪里等等。Perf 还可以替代 strace,可以添加动态内核 probe 点,还可以做 benchmark 衡量调度器的好坏。。。
2.perf 的基本使用
    1)使用 perf list 命令可以列出所有能够触发perf采样点的事件。
     $ perf list 
             List of pre-defined events (to be used in -e): 
             cpu-cycles OR cycles [Hardware event] 
             instructions [Hardware event] 
            …
             cpu-clock [Software event] 
             task-clock [Software event] 
             context-switches OR cs [Software event] 
            …
             ext4:ext4_allocate_inode [Tracepoint event] 
             kmem:kmalloc [Tracepoint event] 
             module:module_load [Tracepoint event] 
             workqueue:workqueue_execution [Tracepoint event] 
             sched:sched_{wakeup,switch} [Tracepoint event] 
             syscalls:sys_{enter,exit}_epoll_wait [Tracepoint event] 
    不同的系统会列出不同的结果,在 2.6.35 版本的内核中,该列表已经相当的长,但无论有多少,我们可以将它们划分为三类:
    Hardware Event 是由 PMU 硬件产生的事件,比如 cache 命中,当您需要了解程序对硬件特性的使用情况时,便需要对这些事件进行采样;
    Software Event 是内核软件产生的事件,比如进程切换,tick 数等 ;
    Tracepoint event 是内核中的静态 tracepoint 所触发的事件,这些 tracepoint 用来判断程序运行期间内核的行为细节,比如 
slab分配器的分配次数等。上述每一个事件都可以用于采样,并生成一项统计数据。

     2)perf stat的使用 
    有些程序慢是因为计算量太大,其多数时间都应该在使用 CPU 进行计算,这叫做 CPU bound 型;有些程序慢是因为过多的 IO,这种时候其CPU 利用率应该不高,这叫做 IO bound 型;对于 CPU bound 程序的调优和 IO bound 的调优是不同的。
    Perf stat 应该是您最先使用的一个工具。它通过概括精简的方式提供被调试程序运行的整体情况和汇总数据。
    现在将源码编译为可执行文件 t1
        gcc – o t1 – g test.c
    下面演示了 perf stat 针对程序 t1 的输出:
         $perf stat ./t1 
         Performance counter stats for './t1': 

         262.738415 task-clock-msecs # 0.991 CPUs 
         2 context-switches # 0.000 M/sec 
         1 CPU-migrations # 0.000 M/sec 
         81 page-faults # 0.000 M/sec 
         9478851 cycles # 36.077 M/sec (scaled from 98.24%) 
         6771 instructions # 0.001 IPC (scaled from 98.99%) 
         111114049 branches # 422.908 M/sec (scaled from 99.37%) 
         8495 branch-misses # 0.008 % (scaled from 95.91%) 
         12152161 cache-references # 46.252 M/sec (scaled from 96.16%) 
         7245338 cache-misses # 27.576 M/sec (scaled from 95.49%) 

          0.265238069 seconds time elapsed 

    上面告诉我们,程序 t1 是一个 CPU bound 型,因为 task-clock-msecs 接近 1。
    对 t1 进行调优应该要找到热点 ( 即最耗时的代码片段 ),再看看是否能够提高热点代码的效率。
    缺省情况下,除了 task-clock-msecs 之外,perf stat 还给出了其他几个最常用的统计信息:
    Task-clock-msecs:CPU 利用率,该值高,说明程序的多数时间花费在 CPU 计算上而非 IO。
    Context-switches:进程切换次数,记录了程序运行过程中发生了多少次进程切换,频繁的进程切换是应该避免的。
    Cache-misses:程序运行过程中总体的 cache 利用情况,如果该值过高,说明程序的 cache 利用不好
    CPU-migrations:表示进程 t1 运行过程中发生了多少次 CPU 迁移,即被调度器从一个 CPU 转移到另外一个 CPU 上运行
    Cycles:处理器时钟,一条机器指令可能需要多个 cycles,
    Instructions: 机器指令数目。
    IPC:是 Instructions/Cycles 的比值,该值越大越好,说明程序充分利用了处理器的特性。
    Cache-references: cache 命中的次数
    Cache-misses: cache 失效的次数。
    通过指定 -e 选项,您可以改变 perf stat 的缺省事件 ( 关于事件,在上一小节已经说明,可以通过 perf list 来查看 )。
假如您已经有很多的调优经验,可能会使用 -e 选项来查看您所感兴趣的特殊的事件。

    3)Perf top 
    用于实时显示当前系统的性能统计信息。该命令主要用来观察整个系统当前的状态,比如可以通过查看该命令的输出来查看当前
系统最耗时的内核函数或某个用户进程。
        举例说明: 一个死循环
            while (1) i++;
    我叫他 t2。启动 t2,然后用 perf top 来观察:
        下面是 perf top 的可能输出:
         PerfTop: 705 irqs/sec kernel:60.4% [1000Hz cycles] 
         -------------------------------------------------- 
         sampl pcnt function DSO 
         1503.00 49.2% t2 
         72.00 2.2% pthread_mutex_lock /lib/libpthread-2.12.so 
         68.00 2.1% delay_tsc [kernel.kallsyms] 
         55.00 1.7% aes_dec_blk [aes_i586] 
         55.00 1.7% drm_clflush_pages [drm] 
         52.00 1.6% system_call [kernel.kallsyms] 
         49.00 1.5% __memcpy_ssse3 /lib/libc-2.12.so 
         48.00 1.4% __strstr_ia32 /lib/libc-2.12.so 
         46.00 1.4% unix_poll [kernel.kallsyms] 
         42.00 1.3% __ieee754_pow /lib/libm-2.12.so 
         41.00 1.2% do_select [kernel.kallsyms] 
         40.00 1.2% pixman_rasterize_edges libpixman-1.so.0.18.0 
         37.00 1.1% _raw_spin_lock_irqsave [kernel.kallsyms] 
         36.00 1.1% _int_malloc /lib/libc-2.12.so 
         ^C
        很容易便发现 t2 是需要关注的可疑程序。不过其作案手法太简单:肆无忌惮地浪费着 CPU。所以我们不用再做什么其他的事情便可以找到问题所在。但现实生活中,影响性能的程序一般都不会如此愚蠢,所以我们往往还需要使用其他的 perf 工具进一步分析。
      通过添加 -e 选项,您可以列出造成其他事件的 TopN 个进程 / 函数。比如 -e cache-miss,用来看看谁造成的 cache miss 最多。
    4)使用 perf record, 解读 report
    使用 top 和 stat 之后,您可能已经大致有数了。要进一步分析,便需要一些粒度更细的信息。比如说您已经断定目标程序计算
量较大,也许是因为有些代码写的不够精简。那么面对长长的代码文件,究竟哪几行代码需要进一步修改呢?这便需要使用 perf 
record 记录单个函数级别的统计信息,并使用 perf report 来显示统计结果。
    调优应该将注意力集中到百分比高的热点代码片段上,假如一段代码只占用整个程序运行时间的 0.1%,即使您将其优化到仅剩一条机器指令,恐怕也只能将整体的程序性能提高 0.1%。俗话说,好钢用在刀刃上,不必我多说了。
        仍以 t1 为例。
         perf record – e cpu-clock ./t1 
         perf report
    不出所料,hot spot 是xxx函数。但,代码是非常复杂难说的。自己写的一个程序居然有近一半的时间花费在 string 类的几个
方法上,string 是 C++ 标准,我绝不可能写出比 STL 更好的代码了。因此我只有找到自己程序中过多使用 string 的地方。因此我很需要按照调用关系(调用树)进行显示的统计信息。
        使用 perf 的 -g 选项便可以得到需要的信息:
         perf record – e cpu-clock – g ./t1 
         perf report
    通过对 calling graph 的分析,能很方便地看到时间都花费在那个函数中,从而针对函数进行相关优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值