關(guān)于Xilinx Zynq-7000帶來(lái)的新的系統(tǒng)設(shè)計(jì)思路,以及Profiling的對(duì)象libjpeg,前文已經(jīng)描述過(guò)了,再此不再贅述。
一. Oprofile簡(jiǎn)介
Profiling是對(duì)不同性能特征的數(shù)據(jù)的形式化總結(jié)或分析,它通常以圖形和表的形式出現(xiàn)。它提供為特定的處理器事件收集的采樣百分?jǐn)?shù)或數(shù)量,比如cache miss rate、TLB miss rate等等。一般來(lái)說(shuō),主要目的是為了找出軟件中的性能瓶頸,然后有針對(duì)性的優(yōu)化以提升軟件的整體性能。
Oprofile 是用于 Linux 的若干種評(píng)測(cè)和性能監(jiān)控工具中的一種。它可以工作在不同的體系結(jié)構(gòu)上,包括ARM, PowerPC, MIPS, IA32, IA64 和 AMD Athlon等等。它的開(kāi)銷(xiāo)很小,從Linux 2.6 版起,它被包含進(jìn)了Linux內(nèi)核中。
Oprofile可以收集有關(guān)處理器事件的信息,幫助用戶(hù)識(shí)別諸如循環(huán)的展開(kāi)、cache的使用率低、低效的類(lèi)型轉(zhuǎn)換和冗余操作、錯(cuò)誤預(yù)測(cè)轉(zhuǎn)移等問(wèn)題。Oprofile是一種細(xì)粒度的工具,可以為指令集或者為函數(shù)、系統(tǒng)調(diào)用或中斷處理例程收集采樣。Oprofile 通過(guò)取樣來(lái)工作。使用收集到的評(píng)測(cè)數(shù)據(jù),用戶(hù)可以很容易地找出性能問(wèn)題。
通過(guò)監(jiān)察CPU的hardware events,oprofile可以在運(yùn)行狀態(tài)下對(duì)整個(gè)Linux系統(tǒng)進(jìn)行profiling。Profiling的對(duì)象可以是Linux kernel (包括modules和interrupt handlers), shared libraries或者應(yīng)用程序。
從0.9.8版本開(kāi)始,oprofile支持Perf_events profiling mode模式。應(yīng)用程序operf被用來(lái)控制profiling過(guò)程;而在legacy mode下,是通過(guò)opcontrol腳本和oprofiled daemon來(lái)完成的。Operf不再象legacy mode那樣需要OProfile kernel driver,它直接和Linux Kernel Performance Events Subsystem打交道。使用operf,就可以用普通用戶(hù)的身份來(lái)profiling用戶(hù)的應(yīng)用程序了,當(dāng)然如果需要對(duì)整個(gè)系統(tǒng)來(lái)profiling的時(shí)候還是需要root權(quán)限的。
如果硬件不支持OProfile使用performance counters,OProfile就只能工作在Timer Mode下了。Timer Mode只能在legacy profiling mode下使用,即只能通過(guò)opcontrol腳本來(lái)控制。
Oprofile的website為:
可以支持的處理器的hardware event類(lèi)型:
對(duì)于Zynq-7000來(lái)說(shuō), 列出了ARM Cortex-A9內(nèi)核PMU(Performance Monitor Unit)所支持的所有hardware event種類(lèi),可以看出oprofile可以支持很多深入處理器內(nèi)部的分析。
提供了一些oprofile生成的結(jié)果,可以方便開(kāi)發(fā)者在開(kāi)始使用之前了解oprofile能夠做到哪些事情。
Oprofile的詳細(xì)使用文檔:
Oprofile的優(yōu)勢(shì):
? 比較低的運(yùn)行開(kāi)銷(xiāo)
? 對(duì)被profiling的對(duì)象影響很小
? 可以profiling中斷服務(wù)程序(interrupt handlers)
? 可以profiling應(yīng)用程序和shared libraries
? 可以profiling dynamically compiled (JIT) code
? 可以對(duì)整個(gè)系統(tǒng)做profiling
? 可以觀察CPU內(nèi)部的細(xì)節(jié),例如cache miss rate
? 可以多源代碼做annotation
? 可以支持instruction-level的profiling
? 可以生成call-graph profiles
不過(guò)OProfile也不是萬(wàn)能的,它也有自己的局限性:
? 只能在x86, ARM, 和PowerPC架構(gòu)上生成call graph profiles
? 不支持100%精確的instruction-level profiling
? 對(duì)dynamically compiled (JIT) code profiling的支持還不完善。
無(wú)論如何,Oprofile的功能都比gprof要強(qiáng)很多,代價(jià)是配置起來(lái)會(huì)比較麻煩。
二. 編譯Oprofile
首先最好在Linux kernel里面選中Oprofile driver,以獲得全面的支持。
下載Linux kernel Source:從 https://github.com/Xilinx/linux-xlnx 可以下載到Xilinx提供的驗(yàn)證好的內(nèi)核。如果不方便使用Linux下的git工具,可以單擊頁(yè)面上的releases找到相應(yīng)的版本下載tar ball。下載的時(shí)候最好選tar.gz格式的,而不是zip格式的,因?yàn)楹笳咴谔幚韘ymbol link的時(shí)候有可能會(huì)出問(wèn)題。
因?yàn)楣P者使用的是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
在配置界面上將以下兩項(xiàng)勾上:
General setup --->
[*] Profiling support
<*> OProfile system profiling
然后make uImage即可生成新的uImage,用來(lái)替換Xilinx Linux pre-built 14.7中的Linux kernel image。同時(shí)我們也需要vmlinux來(lái)檢查profiling的結(jié)果。
Oprofile需要popt, bfd, liberty庫(kù),要在嵌入式單板上使用這些庫(kù),需要手工完成交叉編譯。
針對(duì)popt 1.7,用以下命令完成編譯:
./configure --prefix=/home/wave/xilinx/oprofileprj/rootfs --host=arm-xilinx-linux-gnueabi --with-kernel-support --disable-nls && make && make install
針對(duì)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
不過(guò)--enable-install-libiberty沒(méi)有效果,所以需要手工把libiberty.a和libiberty.h拷貝到相應(yīng)的位置。
針對(duì)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
配置過(guò)程結(jié)束后可能會(huì)有以下提示,因?yàn)闆](méi)有打算用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,重新編譯的沒(méi)有-pg的libjpeg binary以及tool chain的libc打包放到SD卡中,準(zhǔn)備在ZC706開(kāi)發(fā)板上嘗試profile djpeg。
三. 運(yùn)行Oprofile
正常啟動(dòng)嵌入式Linux后,在開(kāi)發(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é)果了,在筆者的平臺(tái)上看到的內(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)可以被正確的解析出來(lái)了,和gprof的結(jié)果基本一致。相比gprof,oprofile可以在更大的范圍內(nèi)完成profiling。
我們還可以用以下命令觀察源代碼中特定行的執(zhí)行時(shí)間,進(jìn)一步縮小優(yōu)化的范圍,達(dá)到事半功倍的效果。
opannotate --source ./djpeg > opannotate.txt
四. 小結(jié)
通過(guò)實(shí)驗(yàn),我們可以看到Oprofile可以提供更豐富的profiling結(jié)果,可以更好的幫助開(kāi)發(fā)者找到瓶頸,通過(guò)有針對(duì)性的優(yōu)化提升軟件性能;profiling的結(jié)果也可以幫助開(kāi)發(fā)者將性能瓶頸代碼通過(guò)Xilinx HLS工具用硬件加速器來(lái)實(shí)現(xiàn),從而為進(jìn)一步提升整個(gè)嵌入式系統(tǒng)的性能打開(kāi)了大門(mén)。
評(píng)論
查看更多