如何使用oprofile对软件做profiling

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用oprofile对软件做profiling相关的知识,希望对你有一定的参考价值。

参考技术A   关于Xilinx Zynq-7000带来的新的系统设计思路,以及Profiling的对象libjpeg,前文已经描述过了,再此不再赘述。

  一. Oprofile简介

  Profiling是对不同性能特征的数据的形式化总结或分析,它通常以图形和表的形式出现。它提供为特定的处理器事件收集的采样百分数或数 量,比如cache miss rate、TLB miss rate等等。一般来说,主要目的是为了找出软件中的性能瓶颈,然后有针对性的优化以提升软件的整体性能。

  Oprofile 是用于 Linux 的若干种评测和性能监控工具中的一种。它可以工作在不同的体系结构上,包括ARM, PowerPC, MIPS, IA32, IA64 和 AMD Athlon等等。它的开销很小,从Linux 2.6 版起,它被包含进了Linux内核中。

  Oprofile可以收集有关处理器事件的信息,帮助用户识别诸如循环的展开、cache的使用率低、低效的类型转换和冗余操作、错误预测转移 等问题。Oprofile是一种细粒度的工具,可以为指令集或者为函数、系统调用或中断处理例程收集采样。Oprofile 通过取样来工作。使用收集到的评测数据,用户可以很容易地找出性能问题。

  通过监察CPU的hardware events,oprofile可以在运行状态下对整个Linux系统进行profiling。Profiling的对象可以是Linux kernel (包括modules和interrupt handlers), shared libraries或者应用程序。

  从0.9.8版本开始,oprofile支持Perf_events profiling mode模式。应用程序operf被用来控制profiling过程;而在legacy mode下,是通过opcontrol脚本和oprofiled daemon来完成的。Operf不再象legacy mode那样需要OProfile kernel driver,它直接和Linux Kernel Performance Events Subsystem打交道。使用operf,就可以用普通用户的身份来profiling用户的应用程序了,当然如果需要对整个系统来profiling 的时候还是需要root权限的。

  如果硬件不支持OProfile使用performance counters,OProfile就只能工作在Timer Mode下了。Timer Mode只能在legacy profiling mode下使用,即只能通过opcontrol脚本来控制。

  Oprofile的website为:http://oprofile.sourceforge.net/

  可以支持的处理器的hardware event类型:http://oprofile.sourceforge.net/docs/

  对于Zynq-7000来说,http://oprofile.sourceforge.net/docs/armv7-ca9- events.php 列出了ARM Cortex-A9内核PMU(Performance Monitor Unit)所支持的所有hardware event种类,可以看出oprofile可以支持很多深入处理器内部的分析。

  http://oprofile.sourceforge.net/examples/ 提供了一些oprofile生成的结果,可以方便开发者在开始使用之前了解oprofile能够做到哪些事情。

  Oprofile的详细使用文档:http://oprofile.sourceforge.net/doc/index.html

  Oprofile的优势:

  ? 比较低的运行开销

  ? 对被profiling的对象影响很小

  ? 可以profiling中断服务程序(interrupt handlers)

  ? 可以profiling应用程序和shared libraries

  ? 可以profiling dynamically compiled (JIT) code

  ? 可以对整个系统做profiling

  ? 可以观察CPU内部的细节,例如cache miss rate

  ? 可以多源代码做annotation

  ? 可以支持instruction-level的profiling

  ? 可以生成call-graph profiles

  不过OProfile也不是万能的,它也有自己的局限性:

  ? 只能在x86, ARM, 和PowerPC架构上生成call graph profiles

  ? 不支持100%精确的instruction-level profiling

  ? 对dynamically compiled (JIT) code profiling的支持还不完善。

  无论如何,Oprofile的功能都比gprof要强很多,代价是配置起来会比较麻烦。

  二. 编译Oprofile

  首先最好在Linux kernel里面选中Oprofile driver,以获得全面的支持。

  下载Linux kernel Source:从https://github.com/Xilinx/linux-xlnx 可以下载到Xilinx提供的验证好的内核。如果不方便使用Linux下的git工具,可以单击页面上的releases找到相应的版本下载tar ball。下载的时候最好选tar.gz格式的,而不是zip格式的,因为后者在处理symbol link的时候有可能会出问题。

  因为笔者使用的是Xilinx Linux pre-built 14.7,所以这里下载的是linux-xlnx-xilinx-v14.7.tar.gz

  解压缩后,用以下命令调出Linux kernel的配置界面:

  export ARCH=arm

  export CROSS_COMPILE=arm-xilinx-linux-gnueabi-

  make xilinx_zynq_defconfig

  make xconfig 或者make menuconfig

  在配置界面上将以下两项勾上:

  General setup --->

  [*] Profiling support

  <*> OProfile system profiling

  然后make uImage即可生成新的uImage,用来替换Xilinx Linux pre-built 14.7中的Linux kernel image。同时我们也需要vmlinux来检查profiling的结果。

  Oprofile需要popt, bfd, liberty库,要在嵌入式单板上使用这些库,需要手工完成交叉编译。

  针对popt 1.7,用以下命令完成编译:

  ./configure --prefix=/home/wave/xilinx/oprofileprj/rootfs --host=arm-xilinx-linux-gnueabi --with-kernel-support --disable-nls && make && make install

  针对binutils 2.24,用以下命令完成编译:

  ./configure --host=arm-xilinx-linux-gnueabi --prefix=/home/wave/xilinx/oprofileprj/rootfs --enable-install-libbfd --enable-install-libiberty --enable-shared && make && make install

  不过--enable-install-libiberty没有效果,所以需要手工把libiberty.a和libiberty.h拷贝到相应的位置。

  针对oprofile 0.9.9,用以下命令完成编译:

  ./configure --host=arm-xilinx-linux-gnueabi --prefix=/home/wave/xilinx/oprofileprj/rootfs --with-kernel-support --with-binutils=/home/wave/xilinx/oprofileprj/rootfs && make && make install

  配置过程结束后可能会有以下提示,因为没有打算用GUI和profile JITed code,所以直接忽视之。

  config.status: executing libtool commands

  Warning: QT version 3 was requested but not found. No GUI will be built.

  Warning: The user account 'oprofile:oprofile' does not exist on the system.

  To profile JITed code, this special user account must exist.

  Please ask your system administrator to add the following user and group:

  user name : 'oprofile'

  group name: 'oprofile'

  The 'oprofile' group must be the default group for the 'oprofile' user.

  将编译完成的uImage,vmlinux,oprofile binary,重新编译的没有-pg的libjpeg binary以及tool chain的libc打包放到SD卡中,准备在ZC706开发板上尝试profile djpeg。

  三. 运行Oprofile

  正常启动嵌入式Linux后,在开发板的console上一次输入以下命令:

  mount /dev/mmcblk0p1 /mnt

  mkdir -p /home/root/work

  cd /home/root/work

  tar zxvf /mnt/jpeg-bin-nopg.tar.gz

  cd jpeg-bin/bin

  cp /mnt/park-2880x1800.jpg .

  export LD_LIBRARY_PATH=/home/root/work/jpeg-bin/lib

  cd /home/root/work

  tar zxvf /mnt/rootfs.tar.gz

  cd rootfs

  chown root:root -R *

  cp -R bin/* /usr/bin

  cp -R lib/* /lib

  cp /bin/which /usr/bin

  cp /bin/dirname /usr/bin

  mkdir -p /home/wave/xilinx/oprofileprj/rootfs/share

  cp -R ./rootfs/* /home/wave/xilinx/oprofileprj/rootfs

  cd /home/root/work

  tar zxvf /mnt/libc.tar.gz

  cp ./lib/libstdc*.* /lib

  mkdir -p /home/wave/xilinx/libjpeg

  cd /home/wave/xilinx/libjpeg

  tar zxvf /mnt/jpeg-9.tar.gz

  cp /mnt/vmlinux /home/root/work

  cd /home/root/work/jpeg-bin/bin

  opcontrol --init

  opcontrol --vmlinux=/home/root/work/vmlinux

  opcontrol --setup --event=CPU_CYCLES:100000::0:1 --session-dir=/home/root/

  operf --vmlinux /home/root/work/vmlinux ./djpeg -bmp park-2880x1800.jpg > result.bmp

  opreport -l ./djpeg

  完成这一步后,我们就可以看到profiling的结果了,在笔者的平台上看到的内容的主要部分如下:

  root@zynq:~/work/jpeg-bin/bin# opreport -l ./djpeg

  Using /home/root/work/jpeg-bin/bin/oprofile_data/samples/ for samples directory.

  CPU: ARM Cortex-A9, speed 666667 MHz (estimated)

  Counted CPU_CYCLES events (CPU cycle) with a unit mask of 0x00 (No unit mask) count 100000

  samples % image name symbol name

  15293 58.6253 libc-2.17.so /lib/libc-2.17.so

  2044 7.8356 libjpeg.so.9.0.0 ycc_rgb_convert

  1964 7.5289 libjpeg.so.9.0.0 jpeg_idct_16x16

  1918 7.3526 libjpeg.so.9.0.0 decode_mcu

  1570 6.0186 libjpeg.so.9.0.0 jpeg_idct_islow

  1567 6.0071 djpeg finish_output_bmp

  528 2.0241 libjpeg.so.9.0.0 jpeg_fill_bit_buffer

  397 1.5219 djpeg put_pixel_rows

  73 0.2798 vmlinux __copy_from_user

  70 0.2683 libjpeg.so.9.0.0 decompress_onepass

  65 0.2492 libjpeg.so.9.0.0 jpeg_huff_decode

  56 0.2147 vmlinux get_page_from_freelist

  50 0.1917 vmlinux __memzero

  45 0.1725 vmlinux __copy_to_user_std

  41 0.1572 vmlinux _raw_spin_unlock_irqrestore

  15 0.0575 vmlinux do_page_fault

  14 0.0537 vmlinux __generic_file_aio_write

  13 0.0498 vmlinux _raw_spin_unlock_irq

  11 0.0422 vmlinux free_hot_cold_page

  11 0.0422 vmlinux vector_swi

  10 0.0383 vmlinux handle_pte_fault

  从结果中我们可以看到libjpeg.so.9.0.0, djpeg和vmlinux中的symbol name已经可以被正确的解析出来了,和gprof的结果基本一致。相比gprof,oprofile可以在更大的范围内完成profiling。

  我们还可以用以下命令观察源代码中特定行的执行时间,进一步缩小优化的范围,达到事半功倍的效果。

  opannotate --source ./djpeg > opannotate.txt

  四. 小结

  通过实验,我们可以看到Oprofile可以提供更丰富的profiling结果,可以更好的帮助开发者找到瓶颈,通过有针对性的优化提升软件 性能;profiling的结果也可以帮助开发者将性能瓶颈代码通过Xilinx HLS工具用硬件加速器来实现,从而为进一步提升整个嵌入式系统的性能打开了大门。

以上是关于如何使用oprofile对软件做profiling的主要内容,如果未能解决你的问题,请参考以下文章

Linux性能调优之gprof和oprofile

Oprofile中的基本疑问

如何使用oprofile计算一部分C程序的执行时间?

使用 perf_events/oprofile 在 Linux 上分析 JIT 的输出?

安卓上的OProfile

在虚拟机中运行的 Linux 上的 oprofile