使用oprofile分析性能瓶颈

使用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%
可以使用gprof, 编译你程序时加 -pg -g

运行之会在当前目录产生 gmon.out

gprof ./your_program_name

就可以看到了

----------------------------------------

使用oprofile 更精确:

opcontrol --reset
opcontrol --init
opcontrol --setup --event=CYCLES:1000
opcontrol --start && ./your_program_name && opcontrol --dump && opcontrol --stop

opreport -l ./your_program_name

就可以看到了,使用oprofile,编译时只要加 -g 就可以了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/453047.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是死锁

死锁是多个进程在运行过程中因竞争资源时产生的一种僵局。 各并发资源彼此等待对方拥有的资源&#xff0c;且在得到对方资源前不释放自己的资源。

python数据工程师 面试题_阿里P7工程师耗时两天整理的292道python大厂面试题,内含解析!...

前言相对于python大家应该都不会陌生吧&#xff01;现在java跟python可以算的是势均力敌了&#xff0c;所以现在学习python 的小伙伴也是越来越多了&#xff0c;可是学完之后就能找到称心如意的工作了吗&#xff1f;很多小伙伴学习Python的时候感觉很简单&#xff0c;但是到了去…

数组复制

在Java里面,可以用复制语句”AB”给基本类型的数据传递值,但是如果A,B是两个同类型的数组&#xff0c;复制就相当于将一个数组变量的引用传递给另一个数组&#xff1b;如果一个数组发生改变&#xff0c;那么引用同一数组的变量也要发生改变。 1.使用FOR循环,将数组的每个元素复…

IntelliJ IDEA 对于generated source的处理

IntelliJ IDEA 对于generated source的处理 学习了&#xff1a;https://stackoverflow.com/questions/5170620/unable-to-use-intellij-with-a-generated-sources-folder 如果有generated source &#xff0c;例如使用gRPC过程中生成的&#xff0c;可以使用鼠标右键点击使之成为…

产生死锁的原因

一 竞争资源&#xff0c;但是资源的数目不能满足进程的需要。 二 进程间推进顺序非法&#xff0c;进程在运行过程中请求和释放资源的顺序不当。

fabric shim安装合约_hyperledger fabric 开发第一个智能合约

一、编写智能合约代码HelloWorld.go&#xff0c;go语言实现&#xff0c;代码很简单&#xff0c;每个合约包含两个方法&#xff0c;Init、Invoke。package mainimport ("fmt""github.com/hyperledger/fabric/core/chaincode/shim""github.com/hyperled…

不能干一辈子开发???

程序员的职业生涯之我见 总是听到下面的论调 程序员干不了一辈子&#xff01; 程序员怎么也不能干一辈子吧&#xff01; 在中国程序员还能干一辈子&#xff1f; 过了&#xff08;30&#xff09;40我就干不动程序员了&#xff01; 每每听…

分布式缓存的25个优秀实践与线上案例 done

杨彪&#xff0c;蚂蚁金服技术专家&#xff0c;《分布式服务架构&#xff1a;原理、设计与实战》和《可伸缩服务架构&#xff1a;框架与中间件》作者。近10年互联网和游戏行业工作经验。本文节选自即将出版的《可伸缩服务架构&#xff1a;框架与中间件》一书&#xff0c;作者&a…

服务器性能估算参考(硬件-应用服务器)

2019独角兽企业重金招聘Python工程师标准>>> Environment(2013-05-24) two identical machines via a GB-Ethernet link a client machine generating HTTP requests with wrk as the load generator a server machine running the respective “benchmarkee”all …

产生死锁的四个必要条件

&#xff08;1&#xff09;互斥条件&#xff1a;进程对所分配到的资源不允许其他进程进行访问&#xff0c;若其他进程访问该资源&#xff0c;只能等待&#xff0c;直至占有该资源的进程使用完成后释放该资源 &#xff08;2&#xff09;请求和保持条件&#xff1a;进程获得一定的…

下拉选择_在管理Excel中实现联动下拉选择

在系统中常常出现这样的情况&#xff1a;由于下拉选择的数量太多了&#xff0c;难以高效选择。为此管理Excel通过通过引入多级联动选择的方式来减少下拉选择的困难度。先看下使用效果&#xff1a;联动下拉选择这个功能&#xff0c;在管理Excel中可以通过比较简单的配置方法实现…

图片预览

// 预览图片yulanFn: function (e) {var arr [];var that this;//获取当前图片的下表var indexw e.currentTarget.dataset.indexw;var index e.currentTarget.dataset.index;//数据源var pictures this.data.banner[indexw].shoppingCarouselList;var picture "http…

风雨20年:我所积累的20条编程经验

原文作者乔纳森丹尼可&#xff08;Jonathan Danylko&#xff09;是一位自由职业的web架构师和程序员&#xff0c;编程经验已超过20年&#xff0c;涉足领域有电子商务、生物技术、房地产、医疗、保险和公用事业。正如乔纳 森在文中所言&#xff0c;本文适合刚毕业的大学生和刚入…

JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)

这里说的js跨域是指通过js在不同的域之间进行数据传输或通信&#xff0c;比如用ajax向一个不同的域请求数据&#xff0c;或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同&#xff0c;都被当作是不同的域。 下表给出了相对 http://store…

xenserver 安装新硬盘_给Xenserver添加新硬盘

首先我们进入到xenserver的Console界面.然后按下enter进入命令模式,接下来.咱们先看看硬盘有没有存在输入fdisk -l出现如下提示:Disk /dev/sda: 500.1 GB, 500107862016 bytes255 heads, 63 sectors/track, 60801 cylindersUnits cylinders of 16065 * 512 8225280 bytesDevi…

go-study

package (包) 一个目录下面所有的.go文件的包名必须相同. 包名一般和目录名相同(是约定, 不是强制), 包名都小写main包是一个特殊的包名, 在main包中, 必须包含func main()函数导入包(import)的时候, 使用的是包所在目录的路径, 路径中不用包含包的名字, 在使用包的时候,直接用…

什么是系统安全状态

指系统能按某种顺序如&#xff08;P1&#xff0c;P2&#xff0c;...&#xff0c;Pn&#xff09;&#xff0c;来为每个进程分配所需要的资源&#xff0c;直至最大需求&#xff0c;使每个进程都可以顺序完成。若系统不存在这样一个安全序列&#xff0c;则称系统处于不安全状态。

SQL零基础学习笔记(一)

真的不知道我写了这么多不同的的学习笔记又没用。。开始SQL零基础学习笔记 百度百科&#xff1a;SQL&#xff08;Structured Query Language)结构化查询语言&#xff0c;是一种数据库查询和程序设计语言&#xff0c;用于存取数据以及查询、更新和管理关系数据库系统。同时也是数…

WPF 列表虚拟化时的滚动方式

ListBox的滚动方式 分为像素滚动和列表项滚动 通过ListBox的附加属性ScrollViewer.CanContentScroll来设置。因此ListBox的默认模板中&#xff0c;含有ScrollViewer&#xff0c;ScrollViewer下存放列表内容 <ScrollViewer FocusVisualStyle"{x:Null}"><Item…