1)收集CPU的performance counter。CPU里面有很多performance counter,打开
之后,会记录CPU某些事件的数量,比如cache miss, 指令数,指令时间等等。这些
counter需要编程才能使用。测量哪一段代码完全由自己掌握。
2)利用编译器的功能,在函数入口和出口自动加回调函数,在回调函数里面,记录入口
和出口的时间。收集这些信息,可以得到函数的调用流程和每个函数所花费的时间。
3)自己在代码里面加入时间测量点,测量某段代码执行的时间。这种工具看起来和#1的
作用差不多,但是由于performance counter编程有很多限制,所以这种工具有时还是有
用处的。
OProfile 的原理比较简单:现在的很多CPU都提供一个所谓性能计数器的东西(performance counter),大致的原理就是程序可以注册告诉CPU对什么event感兴趣(比如CPU_CYCLE,CPU经历了一次时钟周期),然后CPU在执行了相应的操作后,就会在性能计数器上加1,这样程序就可以取出。所以,使用OProfile来定位CPU使用率的问题,就变成了让oprofile收集程序运行过程中哪个可执行程序(或是so)中的哪个function,消耗的CPU CYCLE最多。
OProfile不是每次有了event都会记录下来的,OProfile有一个sample(采样)的概念,其实就是定义经历了多少次event之后,记录下一个sample。所以,如果我们设置经历10000个CPU_CYCLE event之后记录一个sample,那么,最后在oprofile的输出中,一个sample就表示使用了10000个CPU CYCLE。
下面就是如何使用oprofile了。OProfile需要一个内核module,这个module已经被集成进入了Linux 2.6.x内核;此外还有一个用户态的daemon程序,用来收集信息;再此外就是一些utilities了,用来控制oprofile和打印结果。
所以在PC上调试就非常简单,现在大部分的Linux distribution的内核都打开了oprofile的这个module开关,所以只需要下载oprofile的源码,编译就OK了。但是在板子上就有一些麻烦了,如果板子上的内核编译时没有打开oprofile开关,那么就需要重新编译内核。
==================================== Separator ============================================
在PC上,查看内核是否编译了oprofile可以通过这样:
cat /boot/config-`uname -r` | grep OPROFILE
应该有这样两行:
CONFIG_HAVE_OPROFILE=y
CONFIG_OPROFILE=m
这表示打开了OPROFILE,而且oprofile被编译成了一个module。
在板子上的话,就检查板子的kernel包中提供的config文件,看其中的OPROFILE部分,我的ZOOM板子上的信息是:
CONFIG_HAVE_OPROFILE=y
CONFIG_OPROFILE=y
这表示打开了OPROFILE,但是没有编译成module,直接编译进内核了。
==================================== Separator ============================================
OK,接下来就是在scratchbox中编译oprofile的源码,将prefix指到一个自定义的目录,然后将编译好的文件传到板子上。建议将所有东西都拷贝到/usr目录下即可。
接下来就是:
// 不监控linux kernel
opcontrol --no-vmlinux
// 如果要监控linux kernel,那要提供没有压缩过的,而且包含symbol信息的linux kernel文件,也就是vmlinux那个文件
// uImage是去掉了symbol信息的内核文件,zImage是压缩过的内核文件(该文件的开头有一段解压代码,从而是自解压的文件)
opcontrol --vmlinux=<your vmlinux file path>
// 监控CPU_CYCLES event,每10000个event采样一次,内核和用户态的event都监控,生成最多10级的callgraph
// --event中的0是unitmask,1表示监控内核态event,第二个1表示监控用户态event
opcontrol --event=CPU_CYCLES:10000:0:1:1 --callgraph=10
// 启动
opcontrol --start
// 启动要监控的应用程序
......
// 关闭oprofile(这让oprofiled将所有收集到的数据都写入文件)
// oprofile manual中建议使用opcontrol --dump来flush数据从而不用shutdown oprofiled,应该也是可以的
opcontrol --shutdown
// 查看总体summary数据
opreport
// 查看带symbol信息的数据(能看到哪个so/可执行程序的哪个函数使用了多少sample)
opreport -l
// 查看带callgraph的数据(最详尽的数据)
opreport -l -c
example:
# opcontrol --init
# opcontrol --setup --session-dir=/data/oprofile --no-vmlinux --event=CPU_CYCLES:62400 --separate=library --callgraph=8 --image= /system/lib/xxx.so
# opcontrol –-status
# opcontrol --start
# <run gallery for 5 seconds>
# opcontrol --stop
# opreport --session-dir=/data/oprofile
# opreport --session-dir=/data/oprofile -l
参考:
http://blog.csdn.net/yili_xie/archive/2009/12/02/4925648.aspx