關于Xilinx Zynq-7000帶來的新的系統(tǒng)設計思路,以及Profiling的對象libjpeg,前文已經(jīng)描述過了,再此不再贅述。
一. Oprofile簡介
Profiling是對不同性能特征的數(shù)據(jù)的形式化總結(jié)或分析,它通常以圖形和表的形式出現(xiàn)。它提供為特定的處理器事件收集的采樣百分數(shù)或數(shù)量,比如cache miss rate、TLB miss rate等等。一般來說,主要目的是為了找出軟件中的性能瓶頸,然后有針對性的優(yōu)化以提升軟件的整體性能。
Oprofile 是用于 Linux 的若干種評測和性能監(jiān)控工具中的一種。它可以工作在不同的體系結(jié)構上,包括ARM, PowerPC, MIPS, IA32, IA64 和 AMD Athlon等等。它的開銷很小,從Linux 2.6 版起,它被包含進了Linux內(nèi)核中。
Oprofile可以收集有關處理器事件的信息,幫助用戶識別諸如循環(huán)的展開、cache的使用率低、低效的類型轉(zhuǎn)換和冗余操作、錯誤預測轉(zhuǎn)移等問題。Oprofile是一種細粒度的工具,可以為指令集或者為函數(shù)、系統(tǒng)調(diào)用或中斷處理例程收集采樣。Oprofile 通過取樣來工作。使用收集到的評測數(shù)據(jù),用戶可以很容易地找出性能問題。
通過監(jiān)察CPU的hardware events,oprofile可以在運行狀態(tài)下對整個Linux系統(tǒng)進行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用戶的應用程序了,當然如果需要對整個系統(tǒng)來profiling的時候還是需要root權限的。
如果硬件不支持OProfile使用performance counters,OProfile就只能工作在Timer Mode下了。Timer Mode只能在legacy profiling mode下使用,即只能通過opcontrol腳本來控制。
Oprofile的website為:
可以支持的處理器的hardware event類型:
對于Zynq-7000來說, 列出了ARM Cortex-A9內(nèi)核PMU(Performance Monitor Unit)所支持的所有hardware event種類,可以看出oprofile可以支持很多深入處理器內(nèi)部的分析。
提供了一些oprofile生成的結(jié)果,可以方便開發(fā)者在開始使用之前了解oprofile能夠做到哪些事情。
Oprofile的詳細使用文檔:
Oprofile的優(yōu)勢:
? 比較低的運行開銷
? 對被profiling的對象影響很小
? 可以profiling中斷服務程序(interrupt handlers)
? 可以profiling應用程序和shared libraries
? 可以profiling dynamically compiled (JIT) code
? 可以對整個系統(tǒng)做profiling
? 可以觀察CPU內(nèi)部的細節(jié),例如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提供的驗證好的內(nèi)核。如果不方便使用Linux下的git工具,可以單擊頁面上的releases找到相應的版本下載tar ball。下載的時候最好選tar.gz格式的,而不是zip格式的,因為后者在處理symbol link的時候有可能會出問題。
因為筆者使用的是Xilinx Linux pre-built 14.7,所以這里下載的是 linux-xlnx-xilinx-v14.7.tar.gz
解壓縮后,用以下命令調(diào)出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的結(jié)果。
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
配置過程結(jié)束后可能會有以下提示,因為沒有打算用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開發(fā)板上嘗試profile djpeg。
三. 運行Oprofile
正常啟動嵌入式Linux后,在開發(fā)板的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的結(jié)果了,在筆者的平臺上看到的內(nèi)容的主要部分如下:
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
從結(jié)果中我們可以看到libjpeg.so.9.0.0, djpeg和vmlinux中的symbol name已經(jīng)可以被正確的解析出來了,和gprof的結(jié)果基本一致。相比gprof,oprofile可以在更大的范圍內(nèi)完成profiling。
我們還可以用以下命令觀察源代碼中特定行的執(zhí)行時間,進一步縮小優(yōu)化的范圍,達到事半功倍的效果。
opannotate --source ./djpeg > opannotate.txt
四. 小結(jié)
通過實驗,我們可以看到Oprofile可以提供更豐富的profiling結(jié)果,可以更好的幫助開發(fā)者找到瓶頸,通過有針對性的優(yōu)化提升軟件性能;profiling的結(jié)果也可以幫助開發(fā)者將性能瓶頸代碼通過Xilinx HLS工具用硬件加速器來實現(xiàn),從而為進一步提升整個嵌入式系統(tǒng)的性能打開了大門。
評論
查看更多