首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

如何使用oprofile对软件做profiling (二)

如何使用oprofile对软件做profiling (二)

关于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 'oprofileprofile' 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工具用硬件加速器来实现,从而为进一步提升整个嵌入式系统的性能打开了大门。
  • 记录学习中的点点滴滴,让每一天过的更加有意义!
    共同努力,共同学习!------------中电网技术论坛
    记录学习中的点点滴滴,让每一天过的更加有意义!
    返回列表