谁动了我的cpu——oprofile使用札记(转)
引言
cpu无端占用高?应用程序响应慢?苦于没有分析的工具?
oprofile利用cpu硬件层面提供的性能计数器(performance counter),通过计数采样,帮助我们从进程、函数、代码层面找出占用cpu的"罪魁祸首"。下面我们通过实例,了解oprofile的具体使用方法。
常用命令
使用oprofile进行cpu使用情况检测,需要经过初始化、启动检测、导出检测数据、查看检测结果等步骤,以下为常用的oprofile命令。
初始化
- opcontrol --no-vmlinux : 指示oprofile启动检测后,不记录内核模块、内核代码相关统计数据
- opcontrol --init : 加载oprofile模块、oprofile驱动程序
检测控制
- opcontrol --start : 指示oprofile启动检测
- opcontrol --dump : 指示将oprofile检测到的数据写入文件
- opcontrol --reset : 清空之前检测的数据记录
- opcontrol -h : 关闭oprofile进程
查看检测结果
- opreport : 以镜像(image)的角度显示检测结果,进程、动态库、内核模块属于镜像范畴
- opreport -l : 以函数的角度显示检测结果
- opreport -l test : 以函数的角度,针对test进程显示检测结果
- opannotate -s test : 以代码的角度,针对test进程显示检测结果
- opannotate -s /lib64/libc-2.4.so : 以代码的角度,针对libc-2.4.so库显示检测结果
opreport输出解析
正如以上命令解析所言,不加参数的opreport命令从镜像的角度显示cpu的使用情况:
linux # opreport
CPU: Core 2, speed 2128.07 MHz (estimated)
Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000
CPU_CLK_UNHALT.........|
samples | %|
------------------------
31645719 87.6453 no-vmlinux
4361113 10.3592 libend.so
7683 0.1367 libpython2.4.so.1.0
7046 0.1253 op_test
⋯⋯
以上列表按以下形式输出:
samples | %|
-----------------------------------------------------
镜像内发生的采样次数 采样次数所占总采样次数的百分比 镜像名称
因我们在初始化时执行了"opcontrol --no-vmlinux"命令,指示oprofile不对模块和内核进行检测,因而在探测结果中,模块和内核一同显示成no-vmlinux镜像。输出中,libend.so和libpython2.4.so.1.0均为动态库,op_test为进程。以上采样数据表明,检测时间内,cpu主要执行内核和模块代码,用于执行libend.so库函数的比重亦较大,达到10%左右。
进一步地,我们可以查看到进程、动态库中的每个函数在检测时间内占用cpu的情况:
linux # opreport -l
samples % image name app name symbol name
31645719 87.4472 no-vmlinux no-vmlinux /no-vmlinux
4361113 10.3605 libend.so libend.so endless
7046 0.1253 op_test op_test main
⋯⋯
以上输出显示消耗cpu的函数为libend.so库中的endless函数,以及op_test程序中的main函数。
进行oprofile初始化时,若我们执行opcontrol --vmlinux=vmlinux-`uname -r`,指定oprofile对内核和内核模块进行探测,在执行opreport查看检测结果时,内核和内核模块就不再显示为no-vmlinux,而是内核和各个内核模块作为单独的镜像,显示相应cpu占用情况。
使用opannotate从代码层看cpu占用情况
以上介绍了使用oprofile的opreport命令,分别从进程和函数层面查看cpu使用情况的方法。看到这里,有的同学可能有这样的疑问:使用opreport,我找到了消耗cpu的进程A,找到了进程A中最消耗cpu的函数B,进一步地,是否有办法找到函数B中最消耗cpu的那一行代码呢?
oprofile中的opannotate命令可以帮助我们完成这个任务,结合具备调试信息的程序、带有debuginfo的动态库,opannotate命令可显示代码层面占用cpu的统计信息。下面我们通过几个简单的程序实例,说明opannotate命令的使用方法。
首先,我们需要一个消耗cpu的程序,该程序代码如下:
//op_test.c
extern void endless();
int main()
{
int i = 0, j = 0;
for (; i < 10000000; i++ )
{
j++;
}
endless();
return 0;
}
该程序引用了外部函数endless,endless函数定义如下:
//end.c
void endless()
{
int i = 0;
while(1)
{
i++;
}
}
endless函数同样很简单,下面我们将定义了endless函数的end.c进行带调试信息地编译,并生成libend.so动态库文件:
linux # gcc -c -g -fPIC end.c
linux # gcc -shared -fPIC -o libend.so end.o
linux # cp libend.so /usr/lib64/libend.so
接着,带调试信息地编译op_test.c,生成op_test执行文件:
linux # gcc -g -lend -o op_test op_test.c
之后,我们开启oprofile进行检测,并拉起op_test进程:
linux # opcontrol --reset
linux # opcontrol --start
linux # ./op_test &
在程序运行一段时间后,导出检测数据,使用opannotate进行结果查看:
linux # opcontrol --dump
linux # opannotate -s op_test
/*
* Total samples for file : "/tmp/lx/op_test.c"
*
* 7046 100.00
*/
: int main()
:{ /*main total : 7046 100.000 */
: int i = 0, j = 0;
6447 91.4987 : for (; i < 10000000; i++ )
: {
599 8.5013 : j++;
: }
: endless();
: return 0;
:}
以上输出表明,在op_test程序的main函数中,主要消耗cpu的是for循环所在行代码,因该段代码不仅包含变量i的自增运算,还将i与10000000进行比较。
下面显示对自编动态库libend.so的检测结果:
linux # opannotate -s /usr/lib64/libend.so
/*
* Total samples for file : "/tmp/lx/end.c"
*
* 4361113 100.00
*/
: void endless()
: {
: int i = 0;
: while(1)
: {
25661 0.6652 : i++;
4335452 99.3348 : }
: }
查看c库代码占用cpu情况
以上使用opannotate,分别查看了应用程序代码、自编动态库代码的cpu占用情况,对于c库中的代码,我们是否也能查看其消耗cpu的情况呢?
在使用oprofile查看c库代码信息前,需要安装glibc的debuginfo包,安装debuginfo包之后,我们即可以通过opannotate查看到c库代码,以下展示了malloc底层实现函数_int_malloc的部分代码:
linux # opannotate -s /lib64/libc-2.4.so
/*
----------------malloc---------------------
*/
:Void_t *
:_int_malloc( mstate av, size_t bytes )
:{ /* _int_malloc total: 118396 94.9249 */
⋯⋯
: assert((fwd->size & NON_MAIN_ARENA) == 0);
115460 92.5709 : while((unsigned long)(size) < (unsigned long)(fwd->size)) {
1161 0.9308 : fwd = fwd->fd;
: assert((fwd->size & NON_MAIN_ARENA) == 0);
: }
:}
在进行程序性能调优时,根据oprofile检测到的c库代码占用cpu的统计信息,可以判别程序性能瓶颈是否由c库代码引起。若oprofile检测结果显示cpu被过多地用于执行c库中的代码,我们可进一步地采用修改c库代码、升级glibc版本等方法解决c库引发的应用程序性能问题。
小结
本文介绍了使用oprofile工具从进程、函数和代码层面检测cpu使用情况的方法,对于代码层面,分别介绍了查看程序代码、自编动态库代码以及gblic代码cpu统计情况的方法,中间过程使用到opcontrol、opreport、opannotate三个常用的oprofile命令。
当系统出现cpu使用率异常偏高情况时,oprofile不但可以帮助我们分析出是哪一个进程异常使用cpu,还可以揪出进程中占用cpu的函数、代码。在分析应用程序性能瓶颈、进行性能调优时,我们可以通过oprofile,得出程序代码的cpu使用情况,找到最消耗cpu的那部分代码进行分析与调优,做到有的放矢。另外,进行程序性能调优时,我们不应仅仅关注自己编写的上层代码,也应考虑底层库函数,甚至内核对应用程序性能的影响。
关于oprofile工具可用于分析的场景,本文仅介绍了cpu使用情况一种,我们还可以通过oprofile查看高速缓存的利用率、错误的转移预测等信息,"opcontrol --list-events"命令显示了oprofile可检测到的所有事件,更多的oprofile使用方法,请参看oprofile manual。
Reference: oprofile manual
转自:http://www.cnblogs.com/bangerlee/archive/2012/08/30/2659435.html
谁动了我的cpu——oprofile使用札记(转)的更多相关文章
- 谁动了我的cpu——oprofile使用札记
引言 cpu无端占用高?应用程序响应慢?苦于没有分析的工具? oprofile利用cpu硬件层面提供的性能计数器(performance counter),通过计数采样,帮助我们从进程.函数.代码层面 ...
- 管中窥豹——从对象的生命周期梳理JVM内存结构、GC调优、类加载、AOP编程及性能监控
如题,本文的宗旨既是透过对象的生命周期,来梳理JVM内存结构及GC相关知识,并辅以AOP及双亲委派机制原理,学习不仅仅是海绵式的吸收学习,还需要自己去分析why,加深对技术的理解和认知,祝大家早日走上 ...
- Centos6下通过 oprofile分析CPU性能
Centos6下通过 oprofile分析CPU性能 2014-01-18 10:55:15 bobpen 阅读数 2218更多 分类专栏: linux 版权声明:本文为博主原创文章,遵循CC 4 ...
- oprofile
一.原理 在关注事件发生一定次数时,进行一次采样,记录下需要的信息(比如指令寄存器或栈寄存器信息). 二.参数 项 说明 eventname 要关注的事件名称,常用的事件名称及功能如下: CP ...
- OProfile 性能分析工具
OProfile 性能分析工具 官方网站:http://oprofile.sourceforge.net/news/ oprofile.ko模块本文主要介绍Oprofile工具,适用系统的CPU性能分 ...
- oProfile 学习
oProfile工具可以分析CPU的负载量 只要对目标程序加上 -g 后重新编译,即可用oProfile进行分析 例如在测试apache的性能时, 增加 -g 编译选项[crifan@localhos ...
- oprofile使用方法
安装oprofile,然后加载内核模块.#modprobe oprofile,模块加载后开始使用oprofile. 1. 首先设置监视内核,使用debuginfo提供的内核,/boot下面的内核无法使 ...
- 高级性能调试手段(oprofile+gprofile)+内核追踪手段:LTT
http://blog.csdn.net/wlsfling/article/details/5876134http://www.lenky.info/archives/2012/03/1371http ...
- 《Linux调优工具oprofile的演示分析》
根据CPU架构oprofile采样的触发有两种模式:1) NMI模式: 利用处理器的performance counter功能, 指定counter的类型type和累进数量count. 比如 type ...
随机推荐
- [ CodeVS冲杯之路 ] P1098
不充钱,你怎么AC? 题目:http://codevs.cn/problem/1098/ 显然就是使每堆牌达到总体的平均数,尽量使每次移动时的牌数最大,这就类似于飞行棋,将几个棋子叠起来一起走是最优 ...
- [BZOJ4756][Usaco2017 Jan]Promotion Counting 树状数组
4756: [Usaco2017 Jan]Promotion Counting Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 305 Solved: ...
- React+dva.js+typescript实现百度贴吧移动web端
个人练习作品,有bug欢迎在github上提:) github地址:https://github.com/axel10/react-tieba 整个项目中实现起来最麻烦的应该算是滚动位置记忆和路由动画 ...
- Codeforces Round #277.5 (Div. 2) B. BerSU Ball【贪心/双指针/每两个跳舞的人可以配对,并且他们两个的绝对值只差小于等于1,求最多匹配多少对】
B. BerSU Ball time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- ==与equals()区别
equals和==的区别? 经常被简单的理解为equals方法用来比较两个对象是否相同, 而==比较运算符用来比较两个基本数据类型的数值是否相同. 这样的理解无可厚非,但还要透过简单看看本质,才会更清 ...
- 代码编辑器[0] -> Vim/gVim[2] -> Vim 的相关知识
相关知识 / Relevant Knowledge 1 _vimrc编程 / _vimrc Program 1. 注释符", 用于注释 2. 关键词set, 用于设置功能等 3. 关键词im ...
- 【bzoj1076】【SCOI2008】【奖励关】期望最优值dp
[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=60582219 Description 你正在玩你 ...
- 细说JavaScript对象(4): for in 循环
如同 in 运算符一样,使用 for in 循环遍历对象属性时,也将往上遍历整个原型链. // Poisoning Object.prototype Object.prototype.bar = 1; ...
- linux之网络配置相关
ubuntu的网络配置文件在 /etc/network/intrfaces; suse的网络配置在 /etc/sysconfig/network/下面,每个网卡一个配置文件. int ...
- JAVA生成问答式验证码图片,支持加减算法
原文:http://liuguihua0823.iteye.com/blog/1511355 import java.awt.Color; import java.awt.Font; import j ...