Android上oprofile使用说明

Android上oprofile使用说明

1.    目的

本文介绍了oprofile的功能并基于Android 2.1介绍了使用oprofile的基本方法和步骤。本文的读者为软件开发人员和白盒测试人员。

2.    oprofile简介

Oprofile是用于Linux的若干种评测和性能监控工具中的一种,它可以工作在不同的体系结构上,包括IA32、IA64、AMDAthlon系列及ARM等。Oprofile包含在Linux2.5和更高版本的内核中,也包含在大多数较新的Linux发行版本中,在Android中已经集成了Oprofile。

oprofile以很低的开销对系统中所有运行的代码(包括kernel、kernel模块、库、应用程序)进行函数级别的性能分析(function-level profiling),跟踪占用CPU高的函数的调用信息,从而判断程序中哪些地方存在需要优化的性能瓶颈。

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

基于事件的采样是oprofile只记录特定事件(比如L2 cachemiss)的发生次数,当达到用户设定的定值时oprofile就记录一下(采一个样)。这种方式需要CPU内部有性能计数器(performance counter)。

基于时间的采样是oprofile借助OS时钟中断的机制,每个时钟中断oprofile都会记录一次(采一次样),又分为RTC模式(RTC mode,适用于2.2/2.4内核)和定时器中断模式(timer interrupt mode,适用于2.6以上内核)。引入定时器采样模式的目的在于,提供对没有性能计数器的CPU的支持,其精度相对于基于事件的采样要低,并且因为要借助OS时钟中断的支持,对禁用中断的代码oprofile不能对其进行分析。

高通QSD8K处理器具备性能计数器,但当前发布的软件版本只支持定时器模式。

在Android上,oprofile分为target端和host端两部分。target端运行在设备上,主要包括一个内核模块(oprofile.ko)和一个用户空间的守护进程(oprofiled),前者负责访问性能计数器或者注册基于时间采样的函数(使用register_timer_hook注册之,使时钟中断处理程序最后执行profile_tick时可以访问之),并采样置于内核的缓冲区内;后者在后台运行,负责从内核空间收集数据,写入文件。host端运行在PC上,包括一组后处理工具用于从原始采样数据生成可读的分析报告。

3.    oprofile使用方法

本节基于Android 2.1 (Eclair)介绍oprofile的使用方法,在Android 1.6 (Donut)和Android 2.2 (Froyo)上的使用方法与之相似。

在使用oprofile之前,首先必须确保烧到手机上的系统具有root权限,否则无法使用oprofile,并确保/data下有足够的可用空间用于保存采样数据(一般几十MB足够)。依次按照如下步骤操作。

3.1  步骤一:安装target

Android源代码中已经包含了移植好的oprofile源代码,kernel缺省配置选项也已经enable了对oprofile的支持。在将oprofile的target端安装到手机之前,请首先在eng模式下编译源代码,然后按照如下步骤将所需文件复制到手机上:

1. 内核模块oprofile.ko:

在PC上运行:

sourcebuild/envsetup.sh

choosecombo

adb push$ANDROID_PRODUCT_OUT/obj/KERNEL_OBJ/arch/arm/oprofile/oprofile.ko/data

2. 守护进程oprofiled和控制程序opcontrol:

如果手机上烧的system.img是eng模式编出来的,里面已经包含了oprofiled和opcontrol(在/system/xbin/),这一步可以跳过;如果是user模式编出来的system.img则不包含这两个文件,请运行:

adbpush $ANDROID_PRODUCT_OUT/system/xbin/oprofiled/system/xbin

adb push$ANDROID_PRODUCT_OUT/system/xbin/opcontrol /system/xbin

3. elf内核映像文件:

如果要对内核进行profiling,需要将压缩的elf内核映像文件vmlinux复制到手机上,运行:

adb push$ANDROID_PRODUCT_OUT/obj/KERNEL_OBJ/arch/arm/boot/compressed/vmlinux/data

该vmlinux必须与手机上实际运行的内核一致。

3.2  步骤二:计算内核虚拟地址范围

要对内核进行profiling,需要计算内核开始和结束地址:

运行:

adb pull /proc/kallsyms .

在文件kallsyms中查找_text,其数值即为kernel start地址;查找_etext,其数值即为kernel end地址。

3.3  步骤三:将CPU设置在保持最高频率运行

为确保oprofile采样结果的准确性和一致性,在采样开始之前需将CPU设置在保持最高频率运行,为此在adb shell中运行:

mkdir /data/debug

mount -t debugfs debugfs /data/debug

echo 1 >/data/debug/nohlt

echo performance >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

3.4   步骤四:配置oprofile

在adb shell中运行:

insmod /data/oprofile.ko timer=1

opcontrol --setup

oprofiled --session-dir=/data/oprofile--vmlinux=/data/vmlinux --kernel-range=start,end--events=CPU_CYCLES:255:0:50000:0:1:1 --separate-lib=1--separate-kernel=1

说明:

其中--kernel-range中的start和end即为上述步骤二中获得的kernel start地址和kernel end地址。

3.5  步骤五:开始采样

运行需要进行profiling的应用程序或场景,然后在adb shell中运行:

opcontrol --start

此时oprofile已开始采样,可在adb shell中运行:

opcontrol --status

随时查看oprofile运行状态和已采集的样本数。

3.6  步骤六:停止采样

当采集的样本数足够多的时候(根据经验一般数千即可),在adb shell中运行:

opcontrol --stop

3.7  步骤七:上传数据和生成分析结果

在PC上运行:

source build/envsetup.sh

choosecombo

cp $ANDROID_PRODUCT_OUT/obj/KERNEL_OBJ/vmlinux$ANDROID_PRODUCT_OUT/symbols

python$ANDROID_BUILD_TOP/external/oprofile/opimport_pull~/oprofile-result

此时手机上的采样数据经转换后存在PC上~/oprofile-result中,运行以下命令显示分析结果报告:

cd ~/oprofile-result

$OPROFILE_EVENTS_DIR/bin/opreport--session-dir=. -p $ANDROID_PRODUCT_OUT/symbols -d -l

(注:在Android 2.1(Eclair)中执行上面的命令出错,需将opreport换成自己编译的0.9.4版本的opreport,编译步骤参见本文附录。)

注意:执行以上步骤时若遇到如下出错信息:

opreport: error while loading shared libraries:libbfd-2.18.0.20080103.so: cannot open shared object file: No suchfile or directory

可运行如下命令予以解决:

ln -s /usr/lib/libbfd.so/usr/lib/libbfd-2.18.0.20080103.so

3.8  重新运行oprofile

上述步骤一至七完成了一次完整的oprofile采样和分析过程,若要再次运行oprofile,需复位oprofile并清理上一次的采样数据,在adb shell中运行:

opcontrol --shutdown

rm/data/oprofile

umount/data/debug

rm -rf/data/debug

然后重新执行上述步骤三至七进行下一次的采集和分析。

4.    简化oprofile使用步骤的脚本

从上文的介绍可以看到oprofile的使用比较复杂,为简化使用步骤,特编写若干脚本,只需按照如下步骤运行这些脚本即完成oprofile的各项操作:

1.    工作环境准备:①在eng模式下编译源代码;②为使用oprofile创建一个工作目录(例如~/oprofile),将下面附的压缩包oprofile_cmd.zip解开到该目录下,并进入到该目录下;③按照前文3.2节的方法获取kernel start地址和end地址填入op.sh;④确保烧到手机上的系统具有root权限,且所编译的内核源代码与手机上实际运行的内核一致;⑤确保运行过choosecombo;

2.    安装target端:用数据线连接手机和PC,在PC上的oprofile工作目录下运行:

./prepare.sh

(注:若系统是Android 1.6 (Donut),则运行./prepare.sh donut)

3.    采样:运行需要进行profiling的应用程序或场景,然后在adb shell中运行:

cd/data

shop.sh

此时可运行opcontrol --status查看oprofile运行状态和已采集的样本数,当采集的样本数足够多的时候(根据经验一般数千即可),在adb shell中运行:

opcontrol --stop

4.    上传数据:在PC上的oprofile工作目录下运行:

./import.sh

5.    显示分析结果:在PC上的oprofile工作目录下运行:

./report.sh

6.    重新运行oprofile:在adbshell中运行:

cd/data

shopclean.sh

然后重新执行上述步骤3至5。

5.    oprofile分析结果实例

下面是在Android2.1 (Eclair)上对一个运行alphaanimation的应用程序进行oprofile分析的结果:

CPU: CPU with timer interrupt, speed 0 MHz(estimated)

Profiling through timerinterrupt

         TIMER:0|

  samples|     %|

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

    1769 98.4418 app_process

            TIMER:0|

    samples|     %|

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

       1299 73.4313 libskia.so

        386 21.8202 vmlinux

         39  2.2046libdvm.so

         17  0.9610libc.so

           0.5088libui.so

           0.2261libbinder.so

           0.2261libsurfaceflinger.so

           0.2261libutils.so

           0.1696libandroid_runtime.so

           0.0565libGLES_android.so

           0.0565gralloc.qsd8k.so

           0.0565libm.so

           0.0565libstdc++.so

      13  0.7234rild

            TIMER:0|

    samples|     %|

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

          9 69.2308 vmlinux

          4 30.7692 linker

        0.3339vmlinux

        0.2226cnd

            TIMER:0|

    samples|     %|

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

          2 50.0000 linker

          1 25.0000 cnd

          1 25.0000 vmlinux

        0.1113adbd

            TIMER:0|

    samples|     %|

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

          2 100.000 vmlinux

        0.0556init

            TIMER:0|

    samples|     %|

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

          1 100.000 vmlinux

        0.0556port-bridge

            TIMER:0|

    samples|     %|

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

          1 100.000 vmlinux

        0.0556opcontrol

            TIMER:0|

    samples|     %|

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

          1 100.000 vmlinux

 

samples       image name              app name                symbol name

554     30.8292 libskia.so              app_process             S32A_Opaque_BlitRow32_neon

456     25.3756 libskia.so              app_process             S32A_D565_Blend_neon(unsigned short*, unsigned int const*, int,unsigned int, int, int)

128      7.1230 vmlinux                 app_process             __memzero

113      6.2883 libskia.so              app_process             memset_128_loop

78       4.3406 libskia.so              app_process             memset_128_loop

65       3.6171 vmlinux                 app_process             _spin_unlock_irqrestore

20       1.1130 vmlinux                 app_process             get_page_from_freelist

18       1.0017 libskia.so              app_process             Sprite_D32_S32::blitRect(int, int, int, int)

17       0.9460 vmlinux                 app_process             v7wbi_flush_user_tlb_range

16       0.8904 vmlinux                 app_process             free_hot_cold_page

15       0.8347 libskia.so              app_process             Sprite_D16_S32_BlitRowProc::blitRect(int,int, int, int)

13       0.7234 vmlinux                 app_process             _spin_unlock_irq

12       0.6678 libdvm.so               app_process             dalvik_inst

12       0.6678 libskia.so              app_process             SkDraw::drawPaint(SkPaint const&)const

11       0.6121 vmlinux                 app_process             __dabt_usr

11       0.6121 vmlinux                 app_process             v7_dma_flush_range

10       0.5565 libskia.so              app_process             S32A_D565_Opaque_Dither(unsigned short*, unsigned int const*, int,unsigned int, int, int)

...

从以上结果可以看出,在运行alpha animation的过程中,在oprofile采样数据中2D图形库libskia.so占了最高的比例,达73.4313%,具体是libskia.so中的函数S32A_Opaque_BlitRow32_neon和S32A_D565_Blend_neon分别占了最高的前二名,说明在这一过程中最影响性能的瓶颈是在skia库中的这几个函数。

附录 关于在Android1.6 (Donut)上使用oprofile的注意事项

Android 1.6(Donut)中自带的opimport和opreport(位于$OPROFILE_EVENTS_DIR/bin/)是64位的,只能在安装了64位Linux系统的PC上运行,要在32位系统的PC上运行,解决方法是自己编译0.9.4版本的opimport和opreport(因Android 1.6 (Donut)中自带的oprofile是0.9.4版本的)。0.9.4版本oprofile源代码附在下面:(略)

 

编译步骤如下:

sourcebuild/envsetup.sh

choosecombo

tar-zxvf oprofile-0.9.4.tar.gz

cdoprofile-0.9.4

./configure--with-linux=$ANDROID_PRODUCT_OUT/obj/KERNEL_OBJ

make

makeinstall

或者采用Android2.1 (Eclair)以上版本中自带的opimport和opreport(版本为0.9.5)也可以。

此外Android 1.6(Donut)中的脚本$ANDROID_BUILD_TOP/external/oprofile/opimport_pull有问题,可替换成Android 2.1(Eclair)以上版本中的此文件。

参考资料(略)

Forward from http://blog.sina.com.cn/s/blog_69a04cf40100wy35.html


http://blog.csdn.net/starqiqi77/article/details/8177796
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值