oProfile是Linux平台上的一个功能强大的性能分析工具,支持两种采样(sampling)方式:基于事件的采样(eventbased)和基于时间的采样(timebased)。
基于事件的采样是oProfile只记录特定事件(比如L2 cache miss)的发生次数,当达到用户设定的定值时oProfile就记录一下(采一个样)。这种方式需要CPU内部有性能计数器(performace counter)。
基于时间的采样是oProfile借助OS时钟中断的机制,每个时钟中断oProfile都会记录一次(采一次样),引入此种采样方式的目的在于提供对没有性能计数器的CPU的支持,其精度相对于基于事件的采样要低。因为要借助OS时钟中断的支持,对禁用中断的代码oProfile不能对其进行分析。
oProfile在Linux上分两部分:
一个是内核模块(oprofile.ko),
---负责访问性能计数器或者注册基于时间采样的函数(使用register_timer_hook注册之,使时钟中断处理程序最后执行profile_tick时可以访问之),并采样置于内核的缓冲区内
一个为用户空间的守护进程(oprofiled)
---后台运行,负责从内核空间收集数据,写入文件。
1) op_help:列出可用的事件,并带有简短的描述。 2) opcontrol:控制oProfile的数据收集。 3) opreport:对结果进行统计输出。 4) opannaotate:产生带注释的源/汇编文件,源语言级的注释需要编译源文件时已加上调试符号信息的支持。 5) opgprof:产生如gprof相似的结果。 6) oparchive:将所有的原始数据文件收集打包,从而可以在另一台机器上进行分析。 7) opimport:将采样的数据库文件从另一种abi外部格式转化为本地格式。
adb push out/target/product/sp8810ea/obj/KERNEL/arch/arm/oprofile/oprofile.ko /data/ insmod /data/oprofile.ko timer=1 (表示使用计时器中断)
opcontrol --setup opcontrol --session-dir=/data/oprofile --no-vmlinux --events=CPU_CYCLES:1000::0:1 --separate-lib=1
参数说明:
--no-vmlinux 表示不记录内核模块、内核代码相关统计数据, 若需要记录kernel模块,则使用--vmlinux=/data/vmlinux --event=name:count:unitmask:kernel:user (设置计数事件) name: event名字如CPU_CYCLES count: reset counter value (即抽样率) unitmask: hardware unit mask kernel: whether to profile kernel: 0 or 1 user: whether to profile userspace: 0 or 1
例子:
pcontrol --session-dir=/data/oprofile --no-vmlinux --events=CPU_CYCLES:1000::0:1 --separate-lib=1
pcontrol --session-dir=/data/oprofile --vmlinux=/sdcard/vmlinux --events=CPU_CYCLES --kernel-range=0xc0000000,0xffffffff
opcontrol --start
opcontrol --status (查看oprofile运行状态和已采集的样本数)
opcontrol --stop (停止采用,dump所有数据) opcontrol --dump
./external/oprofile 目录下执行
./opimport_pull ~/Downloads/wpa_supplicant/Oprofile/oprofile-result (可以指定具体的目录路径)
若出现:Either OPROFILE_BIN_DIR or ANDROID_HOST_OUT must be set. Run ". envsetup.sh" first
先要执行, source build/envsetup.sh; lunch; 选择对应的产品。
cd ~/Downloads/wpa_supplicant/Oprofile/oprofile-result opreport --session-dir=. -p $ANDROID_PRODUCT_OUT/symbols -l (-l 表示按采样数排列)
重新开始一次新的profile前,需复位oprofile并清理上一次的采样数据:
opcontrol --shutdown rm /data/oprofile
//test.c --> test extern void endless(); int main() { int i = 0, j = 0; for (; i < 10000000; i++ ) { j++; } endless(); return 0; } //test_lib.c --> libtest.so void endless() { int i = 0; while(1) { i++; } }
./opimport_pull ~/Downloads/wpa_supplicant/Oprofile/oprofile-result CPU: CPU with timer interrupt, speed 0 MHz (estimated) Profiling through timer interrupt TIMER:0| samples| %| ------------------ 7088 92.2917 test TIMER:0| samples| %| ------------------ 7088 100.000 libtest.so 571 7.4349 no-vmlinux 13 0.1693 app_process TIMER:0| samples| %| ------------------ 5 38.4615 libdvm.so 4 30.7692 dalvik-jit-code-cache 2 15.3846 libc.so 2 15.3846 libutils.so 3 0.0391 toolbox TIMER:0| samples| %| ------------------ 2 66.6667 linker 1 33.3333 libc.so 2 0.0260 mksh 1 0.0130 adbd 1 0.0130 slog TIMER:0| samples| %| ------------------ 1 100.000 libc.so 1 0.0130 surfaceflinger TIMER:0| samples| %| ------------------ 1 100.000 libbinder.so
opreport --session-dir=. -p $ANDROID_PRODUCT_OUT/symbols -l
warning: /dev/ashmem/dalvik-jit-code-cache could not be found. warning: /no-vmlinux could not be found. CPU: CPU with timer interrupt, speed 0 MHz (estimated) Profiling through timer interrupt warning: could not check that the binary file /home/apuser/Workdir/sprdroid4.1_vlx_3.0/out/target/product/sp8810ea/symbols/sbin/adbd has not been modified since the profile was taken. Results may be inaccurate. samples % image name app name symbol name 7088 92.2917 libtest.so test endless 571 7.4349 no-vmlinux no-vmlinux /no-vmlinux 4 0.0521 dalvik-jit-code-cache app_process /dev/ashmem/dalvik-jit-code-cache 1 0.0130 adbd adbd __aeabi_uidiv 1 0.0130 libbinder.so surfaceflinger android::BBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int) 1 0.0130 libc.so app_process __divdi3 1 0.0130 libc.so app_process dlmalloc_walk_free_pages 1 0.0130 libc.so slog __vfprintf 1 0.0130 libc.so toolbox __sfvwrite 1 0.0130 libdvm.so app_process common_invokeMethodNoRange 1 0.0130 libdvm.so app_process dalvik_inst 1 0.0130 libdvm.so app_process dvmChangeStatus(Thread*, ThreadStatus) 1 0.0130 libdvm.so app_process dvmInterpHandlePackedSwitch 1 0.0130 libdvm.so app_process scanObject(Object const*, GcMarkContext*) 1 0.0130 libutils.so app_process android::Looper::wake() 1 0.0130 libutils.so app_process android::uptimeMillis() 1 0.0130 linker toolbox __dl_$t 1 0.0130 linker toolbox __dl_$t 1 0.0130 mksh mksh comexec 1 0.0130 mksh mksh ktscan
opannotate --session-dir=. -p $ANDROID_PRODUCT_OUT/symbols -s $ANDROID_PRODUCT_OUT/symbols/system/bin/test
/* * Command line: opannotate --session-dir=. -p /home/apuser/Workdir/sprdroid4.1_vlx_3.0/out/target/product/sp8810ea/symbols -s /home/apuser/Workdir/sprdroid4.1_vlx_3.0/out/target/product/sp8810ea/symbols/system/bin/test * * Interpretation of command line: * Output annotated source file with samples * Output all files * * CPU: CPU with timer interrupt, speed 0 MHz (estimated) * Profiling through timer interrupt */ /* * Total samples for file : "/home/apuser/Workdir/sprdroid4.1_vlx_3.0/external/oprofile_test/test_lib.c" * * 7088 100.000 */ ://end.c :void endless() 7088 100.000 :{ /* endless total: 7088 100.000 */ : int i = 0; : while(1) : { : i++; : } :}
. external/oprofile$ ./opimport_pull ~/Downloads/wpa_supplicant/Oprofile/oprofile-result
CPU: CPU with timer interrupt, speed 0 MHz (estimated) Profiling through timer interrupt TIMER:0| samples| %| ------------------ 3631 98.6149 vmlinux 14 0.3802 adbd TIMER:0| samples| %| ------------------ 12 85.7143 vmlinux 2 14.2857 adbd 13 0.3531 mksh TIMER:0| samples| %| ------------------ 6 46.1538 vmlinux 4 30.7692 libc.so 3 23.0769 mksh 10 0.2716 opcontrol TIMER:0| samples| %| ------------------ 8 80.0000 vmlinux 1 10.0000 linker 1 10.0000 libc.so 4 0.1086 app_process TIMER:0| samples| %| ------------------ 1 25.0000 vmlinux 1 25.0000 dalvik-jit-code-cache 1 25.0000 libandroid_runtime.so 1 25.0000 libc.so 4 0.1086 slog TIMER:0| samples| %| ------------------ 3 75.0000 vmlinux 1 25.0000 libc.so 3 0.0815 toolbox TIMER:0| samples| %| ------------------ 3 100.000 vmlinux 2 0.0543 surfaceflinger TIMER:0| samples| %| ------------------ 2 100.000 vmlinux 1 0.0272 oprofiled
cp $ANDROID_PRODUCT_OUT/obj/KERNEL/vmlinux $ANDROID_PRODUCT_OUT/symbols (将对应的vmlinux放到symbols目录,方便下面执行符号分析)
opreport --session-dir=. -p $ANDROID_PRODUCT_OUT/symbols -l
warning: /dev/ashmem/dalvik-jit-code-cache could not be found. CPU: CPU with timer interrupt, speed 0 MHz (estimated) Profiling through timer interrupt warning: could not check that the binary file /home/apuser/Workdir/sprdroid4.1_vlx_3.0/out/target/product/sp8810ea/symbols/sbin/adbd has not been modified since the profile was taken. Results may be inaccurate. samples % image name app name symbol name 3602 97.8273 vmlinux vmlinux sc8810_idle 11 0.2988 vmlinux vmlinux __delay 8 0.2173 vmlinux vmlinux sdhci_set_ios 3 0.0815 vmlinux toolbox copy_page 3 0.0815 vmlinux vmlinux sci_adc_get_value 2 0.0543 vmlinux adbd __schedule 2 0.0543 vmlinux vmlinux vprintk 1 0.0272 adbd adbd fdevent_process 1 0.0272 adbd adbd memcpy 1 0.0272 dalvik-jit-code-cache app_process /dev/ashmem/dalvik-jit-code-cache 1 0.0272 libandroid_runtime.so app_process android::AndroidRuntime::getJNIEnv() 1 0.0272 libc.so app_process __aeabi_ldivmod 1 0.0272 libc.so mksh __vfprintf 1 0.0272 libc.so mksh dlmalloc 1 0.0272 libc.so mksh getenv 1 0.0272 libc.so mksh memmove 1 0.0272 libc.so opcontrol memcmp 1 0.0272 libc.so slog strchr 1 0.0272 linker opcontrol __dl_$t 1 0.0272 mksh mksh afreeall 1 0.0272 mksh mksh comexec 1 0.0272 mksh mksh exchild 1 0.0272 oprofiled oprofiled sfile_find 1 0.0272 vmlinux adbd __pollwait 1 0.0272 vmlinux adbd __rcu_read_unlock 1 0.0272 vmlinux adbd __wake_up_sync_key 1 0.0272 vmlinux adbd do_vfp 1 0.0272 vmlinux adbd fget_light 1 0.0272 vmlinux adbd flush_work 1 0.0272 vmlinux adbd free_pages_prepare 1 0.0272 vmlinux adbd n_tty_read 1 0.0272 vmlinux adbd skb_queue_tail 1 0.0272 vmlinux adbd sock_alloc_send_pskb 1 0.0272 vmlinux app_process sprd_gptimer_read 1 0.0272 vmlinux mksh __sync_icache_dcache 1 0.0272 vmlinux mksh __up_read 1 0.0272 vmlinux mksh copy_page 1 0.0272 vmlinux mksh free_pages_prepare 1 0.0272 vmlinux mksh sys_mprotect 1 0.0272 vmlinux mksh unmap_region 1 0.0272 vmlinux opcontrol __dentry_open 1 0.0272 vmlinux opcontrol __schedule 1 0.0272 vmlinux opcontrol cpu_v7_set_pte_ext 1 0.0272 vmlinux opcontrol get_page_from_freelist 1 0.0272 vmlinux opcontrol link_path_walk 1 0.0272 vmlinux opcontrol md5_transform 1 0.0272 vmlinux opcontrol mmap_region 1 0.0272 vmlinux opcontrol touch_atime 1 0.0272 vmlinux slog copy_page 1 0.0272 vmlinux slog do_select 1 0.0272 vmlinux slog schedule_hrtimeout_range_clock 1 0.0272 vmlinux surfaceflinger can_nice 1 0.0272 vmlinux surfaceflinger futex_wait_queue_me 1 0.0272 vmlinux vmlinux fsg_main_thread 1 0.0272 vmlinux vmlinux jbd2_journal_cancel_revoke 1 0.0272 vmlinux vmlinux n_tty_receive_buf 1 0.0272 vmlinux vmlinux thumbee_notifier 1 0.0272 vmlinux vmlinux tick_nohz_restart_sched_tick