之前介绍过oprofile的移植,现在通过一个例子介绍一下oprofile的使用。
1.先打开一个控制台窗口(用来查看系统的CPU状况)
2.进入手机shell打开oprofile
C:/Users/louieli.TENCENT>adb shell
# export PATH=/data/oprofile/bin:$PATH //设置环境变量
export PATH=/data/oprofile/bin:$PATH
# mkdir /dev/oprofile //Oprofile需要这个目录
mkdir /dev/oprofile
# mount -t oprofilefs nodev /dev/oprofile //Oprofile会检测oprofilefs是否存在
mount -t oprofilefs nodev /dev/oprofile
# opcontrol --init //初始化,只需要做一次
opcontrol --init
# mount -o remount rw / //修改根目录为读写
mount -o remount rw /
# opcontrol --session-dir=/data/result --no-vmlinux --separate=lib //设置oprofile参数,只需要做一次
opcontrol --session-dir=/data/result --no-vmlinux --separate=lib
# opcontrol --start //启动侦听
opcontrol --start
Detected stale lock file. Removing.
Using default event: CPU_CYCLES:100000:0:1:1
Using 2.6+ OProfile kernel interface.
Using log file /data/result/samples/oprofiled.log
Daemon started.
Profiler running.
#
3.启动我们的应用icu_app
4.启动method profiling
5.让我们的被测应用运行一会儿
6.依次停止method profiling和被测程序
被程序运行期间的Cpu占用
7.收集Oprofile数据
# opcontrol --dump //收集数据
opcontrol --dump
# opcontrol --stop //停止侦听
opcontrol --stop
Stopping profiling.
# opcontrol --shutdown //关闭侦听进程
opcontrol --shutdown
Killing daemon.
#
注意:如果要再次侦听只需依次执行opcontrol --reset 和opcontrol --start即可
8.分析数据
先看一下占用最多CPU的是哪个程序
# opreport --session-dir=/data/result -t 5
opreport --session-dir=/data/result -t 5
CPU: ARM V6 PMU, speed 0 MHz (estimated)
Counted CPU_CYCLES events (clock cycles counter) with a unit mask of 0x00 (No unit mask) count 100000
CPU_CYCLES:100000|
samples| %|
------------------
3002706 59.1212 app_process
CPU_CYCLES:100000|
samples| %|
------------------
1919285 63.9185 libdvm.so (耗时最多)
264603 8.8122 libandroid_runtime.so
231639 7.7143 libc.so
188271 6.2700 libskia.so
187691 6.2507 libicu_video.so (被测应用的so文件)
34843 1.1604 libcutils.so
27050 0.9009 libGLES_android.so
23593 0.7857 libbinder.so
21925 0.7302 libui.so
21419 0.7133 libutils.so
20870 0.6950 linker
20565 0.6849 libsurfaceflinger.so
14220 0.4736 libavcodec.so
5030 0.1675 libpixelflinger.so
4325 0.1440 copybit.msm7k.so
2947 0.0981 libhardware.so
2055 0.0684 libGLESv1_CM.so
1914 0.0637 libEGL.so
1801 0.0600 libm.so
1490 0.0496 gralloc.msm7k.so
1353 0.0451 libicuuc.so
1244 0.0414 libz.so
913 0.0304 liblog.so
695 0.0231 libstdc++.so
687 0.0229 libsqlite.so
541 0.0180 libnativehelper.so
505 0.0168 sensors.hero.so
367 0.0122 libcrypto.so
314 0.0105 libicui18n.so
242 0.0081 librpc.so
125 0.0042 libgps.so
69 0.0023 libhardware_legacy.so
43 0.0014 libandroid_servers.so
31 0.0010 libwpa_client.so
14 4.7e-04 libssl.so
10 3.3e-04 libmedia.so
8 2.7e-04 libstlport.so
5 1.7e-04 lights.hero.so
1 3.3e-05 app_process
1 3.3e-05 [heap] (tgid:10891 range:0xa000-0xa7000)
1 3.3e-05 libicu_audio.so (被测应用的so文件)
1 3.3e-05 libemoji.so
1718004 33.8263 no-vmlinux
从上面的数据可以看到是libdvm.so占用了大部分的CPU时间,究竟libdvm.so在干嘛呢?我们可以通过traceview看到
从图上可以看出大部份的CPU时间都在做垃圾回收,现在我们就可以根据可能造成GC的情况进行排查,究竟是程序的原因,还是硬件配置的原因。
下面我们看看我们自己的so的执行情况,
# opreport --session-dir=/data/result -t 1 -l /data/data/com.tencent.IcuApp/lib/libicu_video.so
CPU: ARM V6 PMU, speed 0 MHz (estimated)
Counted CPU_CYCLES events (clock cycles counter) with a unit mask of 0x00 (No unit mask) count 100000
samples % image name symbol name
142223 76.9068 libicu_video.so hloop
9377 5.0706 libicu_video.so vpx_codec_peek_stream_info
5178 2.8000 libicu_video.so QQ_UTIL::QQSocket::WaitEvent(unsigned short, unsigned long)
4764 2.5761 libicu_video.so rtp_timer_mgr::timer_theard_proc()
有了这些信息,我们就可以有针对性的对程序进行调优了。