首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 使用oprofile分析性能瓶颈
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • wzzwt
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2007-08-07 10:52:31 楼主
    使用oprofile分析性能瓶颈


    1.   概述

    oprofile   是   Linux   平台上,类似   INTEL   VTune   的一个功能强大的性能分析工具。

    其支持两种采样(sampling)方式:基于事件的采样(event   based)和基于时间的采样(time   based)。

    基于事件的采样是oprofile只记录特定事件(比如L2   cache   miss)的发生次数,当达到用户设定的
    定值时oprofile   就记录一下(采一个样)。这种方式需要CPU   内部有性能计数器(performace   counter)。
    现代CPU内部一般都有性能计数器,龙芯2E内部亦内置了2个性能计数器。

    基于时间的采样是oprofile   借助OS   时钟中断的机制,每个时钟中断   oprofile   都会记录一次(采一次样)。
    引入的目的在于,提供对没有性能计数器   CPU   的支持。其精度相对于基于事件的采样要低。因为要借助   OS
    时钟中断的支持,对禁用中断的代码oprofile不能对其进行分析。

    oprofile   在Linux   上分两部分,一个是内核模块(oprofile.ko),一个为用户空间的守护进程(oprofiled)。
    前者负责访问性能计数器或者注册基于时间采样的函数(使用register_timer_hook注册之,使时钟中断处理
    程序最后执行profile_tick   时可以访问之),并采样置于内核的缓冲区内。后者在后台运行,负责从内核空
    间收集数据,写入文件。


    2.   oprofile   的安装

    以龙芯2E平台为例,要使用oprofile   首先得采用打开oprofile支持的内核启动。然后安装下面3个软件包:
    oprofile,   oprofile-common,   oprofile-gui,其中核心软件包是oprofile-common,其包括以下工具集:

                    /usr/bin/oprofiled                                 守护进程
                    /usr/bin/opcontrol                                 控制前端,负责控制与用户交互,用得最多                
                    /usr/bin/opannotate                                 根据搜集到的数据,在源码或者汇编层面上注释并呈现给用户
                    /usr/bin/opreport                                 生成二进制镜像或符号的概览
                    /usr/bin/ophelp                                                 列出oprofile支持的事件
                    /usr/bin/opgprof                                 生成gprof格式的剖析数据
                    ...


    目前oprofile   在龙芯2E上已经移植好了,包括用户空间的工具集软件包,亦可用矣。

    一个测试用的内核,已经打开   oprofile   ,位于   http://people.openrays.org/~comcat/godson/vmlinux-2.6.18-oprofile

    用户空间工具集deb   包位于:   http://people.openrays.org/~comcat/godson/oprofile-0.9.2/


    3.   oprofile   快速上手

    a.   初始化

                    opcontrol   --init

                    该命令会加载oprofile.ko模块,mount   oprofilefs。成功后会在/dev/oprofile/目录下导出
                    一些文件和目录如:   cpu_type,   dump,   enable,   pointer_size,   stats/

    b.   配置

                    主要设置计数事件和样本计数,以及计数的CPU模式(用户态、核心态)
                   
                    opcontrol   --setup   --event=CYCLES:1000::0:1

                    则是设置计数事件为CYCLES,即对处理器时钟周期进行计数
                    样本计数为1000,即每1000个时钟周期,oprofile   取样一次。
                    处理器运行于核心态则不计数
                    运行于用户态则计数

                    --event=name:count:unitmask:kernel:user

                name:           event   name,   e.g.   CYCLES   or   ICACHE_MISSES  
                count:         reset   counter   value   e.g.   100000
                unitmask:   hardware   unit   mask   e.g.   0x0f
                kernel:       whether   to   profile   kernel:   0   or   1
                user:           whether   to   profile   userspace:   0   or   1

    c.   启动

                    opcontrol   --start


    d.   运行待分析之程序

                    ./ffmpeg   -c   cif   -vcodec   mpeg4   -i   /root/paris.yuv   paris.avi

    e.   取出数据

                    opcontrol   --dump
                    opcontrol   --stop

    f.   分析结果

                    opreport   -l   ./ffmpeg


    则会输出如下结果:

    CPU:   GODSON2E,   speed   0   MHz   (estimated)
    Counted   CYCLES   events   (Cycles)   with   a   unit   mask   of   0x00   (No   unit   mask)   count   10000
    samples     %                 symbol   name
    11739         27.0148     pix_abs16_c
    6052           13.9274     pix_abs16_xy2_c
    4439           10.2154     ff_jpeg_fdct_islow
    2574             5.9235     pix_abs16_y2_c
    2555             5.8798     dct_quantize_c
    2514             5.7854     pix_abs8_c
    2358             5.4264     pix_abs16_x2_c
    1388             3.1942     diff_pixels_c
    964               2.2184     ff_estimate_p_frame_motion
    852               1.9607     simple_idct_add
    768               1.7674     sse16_c
    751               1.7283     ff_epzs_motion_search
    735               1.6914     pix_norm1_c
    619               1.4245     pix_sum_c
    561               1.2910     mpeg4_encode_blocks
    558               1.2841     encode_thread
    269               0.6190     put_no_rnd_pixels16_c
    255               0.5868     dct_unquantize_h263_inter_c

    ......


    4.   例子

    oprofile   可以分析处理器周期、TLB   失误、分支预测失误、缓存失误、中断处理程序,等等。
    你可以使用   opcontrol   --list-events   列出当前处理器上可监视事件列表。

    下面分析一个编写不当的例子:


    [带有cache问题的代码cache.c]
    +++++++++++++++++++++++++++++++++++++++++++++++

    int   matrix[2047][7];


    void   bad_access()
    {
            int   k,   j,   sum   =   0;

            for(k   =   0;   k   <   7;   k++)
                    for(j   =   0;   j   <   2047;   j++)
                            sum   +=   matrix[j][k]   *   1024;

    }

    int   main()
    {
                    int   i;

                    for(i   =   0;   i <   100000;   i++)
                                    bad_access();

                    return   0;

    }

    +++++++++++++++++++++++++++++++++++++++++++++++


    编译之:   gcc   -g   cache.c   -o   cache


    使用oprofile   分析之:

    opcontrol   --init

    opcontrol   --setup   --event=DCACHE_MISSES:500::0:1

    opcontrol   --start   &&   ./cache   &&   opcontrol   --dump   &&   opcontrol   --stop


    使用   opannotate   分析结果为:

    /*
    *   Command   line:   opannotate   --source   ./cachee
    *
    *   Interpretation   of   command   line:
    *   Output   annotated   source   file   with   samples
    *   Output   all   files
    *
    *   CPU:   GODSON2E,   speed   0   MHz   (estimated)
    *   Counted   ICACHE_MISSES   events   (Instruction   Cache   misses   number   )   with   a   unit   mask   of   0x00   (No   unit   mask)   count   500
    */
    /*
    *   Total   samples   for   file   :   "/comcat/test/pmc.test/cachee.c "
    *
    *           34   100.000
    */


                                  :int   matrix[2047][7];
                                  :
                                  :void   bad_access()
                                  :{   /*   bad_access   total:           33   97.0588   */
                                  :         int   k,   j,   sum   =   0;
                                  :
                                  :         for(k   =   0;   k   <   7;   k++)
            33   97.0588   :                 for(j   =   0;   j   <   2047;   j++)
                                  :                         sum   +=   matrix[j][k]   *   1024;
                                  :
                                  :}
                                  :
                                  :int   main()
                                  :{   /*   main   total:             1     2.9412   */
                                  :         int   i;
                                  :
              1     2.9412   :         for(i   =   0;   i <   10000;   i++)
                                  :                                 bad_access();
                                  :
                                  :         return   0;
                                  :
                                  :}
                                  :


    opreport   解析的结果为:

    GodSonSmall:/comcat/test/pmc.test#   opreport   -l   ./cache
    CPU:   GODSON2E,   speed   0   MHz   (estimated)
    Counted   ICACHE_MISSES   events   (Instruction   Cache   misses   number   )   with   a   unit   mask   of   0x00   (No   unit   mask)   count   500
    samples     %                 symbol   name
    33               97.0588     bad_access
    1                   2.9412     main

    可以看到bad_access()   cache   miss   事件的样本共有33个,占总数的97%


    改进   bad_access()   为   good_access()   后:

    void   good_access()
    {
            int   k,   j,   sum   =   0;

            for(k   =   0;   k   <   2047;   k++)
                    for(j   =   0;   j   <   7;   j++)
                            sum   +=   matrix[k][j]   *   1024;

    }


    CPU:   GODSON2E,   speed   0   MHz   (estimated)
    Counted   ICACHE_MISSES   events   (Instruction   Cache   misses   number   )   with   a   unit   mask   of   0x00   (No   unit   mask)   count   500
    samples     %                 symbol   name
    22               95.6522     good_access
    1                   4.3478     main

    可以看到改进后   cache   miss   事件的样本减少为22个,占总数的95%
    http://www.lemote.com/bbs/viewthread.php?tid=7973
    20  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • C_247
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2007-09-12 16:39:091楼 得分:0
    路过
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • david_xie
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2007-09-13 15:57:452楼 得分:0
    学习,顶
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zy_914
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2007-09-18 21:00:333楼 得分:0
    UP
    修改 删除 举报 引用 回复