編輯:關於Android編程
Android上oprofile使用說明
1. 目的
本文介紹了oprofile的功能並基於Android 2.1介紹了使用oprofile的基本方法和步驟。本文的讀者為軟件開發人員和白盒測試人員。
2. oprofile簡介
Oprofile是用於Linux的若干種評測和性能監控工具中的一種,它可以工作在不同的體系結構上,包括IA32、IA64、AMD Athlon系列及ARM等。Oprofile包含在Linux 2.5和更高版本的內核中,也包含在大多數較新的Linux發行版本中,在Android中已經集成了Oprofile。
oprofile以很低的開銷對系統中所有運行的代碼(包括kernel、kernel模塊、庫、應用程序)進行函數級別的性能分析(function-level profiling),跟蹤占用CPU高的函數的調用信息,從而判斷程序中哪些地方存在需要優化的性能瓶頸。
oprofile支持兩種采樣(sampling)方式:基於事件的采樣(event based)和基於時間的采樣(time based)。
基於事件的采樣是oprofile只記錄特定事件(比如L2 cache miss)的發生次數,當達到用戶設定的定值時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上運行:
source build/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則不包含這兩個文件,請運行:
adb push $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 such file 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
sh op.sh
此時可運行opcontrol --status查看oprofile運行狀態和已采集的樣本數,當采集的樣本數足夠多的時候(根據經驗一般數千即可),在adb shell中運行:
opcontrol --stop
4. 上傳數據:在PC上的oprofile工作目錄下運行:
./import.sh
5. 顯示分析結果:在PC上的oprofile工作目錄下運行:
./report.sh
6. 重新運行oprofile:在adb shell中運行:
cd /data
sh opclean.sh
然後重新執行上述步驟3至5。
5. oprofile分析結果實例
下面是在Android 2.1 (Eclair)上對一個運行alpha animation的應用程序進行oprofile分析的結果:
CPU: CPU with timer interrupt, speed 0 MHz (estimated)
Profiling through timer interrupt
TIMER:0|
samples| %|
------------------
1769 98.4418 app_process
TIMER:0|
samples| %|
------------------
1299 73.4313 libskia.so
386 21.8202 vmlinux
39 2.2046 libdvm.so
17 0.9610 libc.so
9 0.5088 libui.so
4 0.2261 libbinder.so
4 0.2261 libsurfaceflinger.so
4 0.2261 libutils.so
3 0.1696 libandroid_runtime.so
1 0.0565 libGLES_android.so
1 0.0565 gralloc.qsd8k.so
1 0.0565 libm.so
1 0.0565 libstdc++.so
13 0.7234 rild
TIMER:0|
samples| %|
------------------
9 69.2308 vmlinux
4 30.7692 linker
6 0.3339 vmlinux
4 0.2226 cnd
TIMER:0|
samples| %|
------------------
2 50.0000 linker
1 25.0000 cnd
1 25.0000 vmlinux
2 0.1113 adbd
TIMER:0|
samples| %|
------------------
2 100.000 vmlinux
1 0.0556 init
TIMER:0|
samples| %|
------------------
1 100.000 vmlinux
1 0.0556 port-bridge
TIMER:0|
samples| %|
------------------
1 100.000 vmlinux
1 0.0556 opcontrol
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庫中的這幾個函數。
附錄 關於在Android 1.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源代碼附在下面:(略)
編譯步驟如下:
source build/envsetup.sh
choosecombo
tar -zxvf oprofile-0.9.4.tar.gz
cd oprofile-0.9.4
./configure --with-linux=$ANDROID_PRODUCT_OUT/obj/KERNEL_OBJ
make
make install
或者采用Android 2.1 (Eclair)以上版本中自帶的opimport和opreport(版本為0.9.5)也可以。
此外Android 1.6 (Donut)中的腳本$ANDROID_BUILD_TOP/external/oprofile/opimport_pull有問題,可替換成Android 2.1 (Eclair)以上版本中的此文件。
作者:迷糊
獲得網絡上圖片的過程: 顯示出來 首先,我們要添加權限 因為我們要訪問網絡,所以我們要在AndroidManifest.xml文件總添加網絡訪問權限: 然後就
There are many great advantages to building your own UI components, such as the abili
前言 心好疼:昨晚寫完了這篇博客一半,今天編輯的時候網絡突然斷了,我的文章就這樣沒了,但是為了Developer的使用AS這款IDE可以快速上手,我還是繼續進行詳解
Android的廣告平台是很多的,各市場對各平台的接受程度是不一樣的,Android的開發者如果想集成廣告基本要考慮下面兩個問題:(1)集成什麼廣告,會賺錢?(2)集成什