使用Profiling工具進(jìn)行代碼性能優(yōu)化_第1頁
使用Profiling工具進(jìn)行代碼性能優(yōu)化_第2頁
使用Profiling工具進(jìn)行代碼性能優(yōu)化_第3頁
使用Profiling工具進(jìn)行代碼性能優(yōu)化_第4頁
使用Profiling工具進(jìn)行代碼性能優(yōu)化_第5頁
已閱讀5頁,還剩23頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

TOC\o"1-5"\h\z0.文檔說明3\o"CurrentDocument"使用OProfile進(jìn)行性能分析3\o"CurrentDocument"OProfile的簡介3\o"CurrentDocument"1.1.1使用OProfile的動(dòng)機(jī)和約束3\o"CurrentDocument"1.1.2使用OProfile的系統(tǒng)需求.4\o"CurrentDocument"1.1.3其他關(guān)于OProfile的可用資源5\o"CurrentDocument"安裝OProfile5Oprofile概述6開始6\o"CurrentDocument"1.2.2工具小節(jié)6控制Profiler.7使用opcontrol.7\o"CurrentDocument"使用oprof_start10\o"CurrentDocument"1.3.3配置細(xì)節(jié)10\o"CurrentDocument"1.4獲得結(jié)果11\o"CurrentDocument"ProfileSpecification11\o"CurrentDocument"1.4.2.鏡像與符號(hào)的結(jié)果匯總(使用opreport)14\o"CurrentDocument"1.4.3輸出帶標(biāo)注的源碼18\o"CurrentDocument"gprof兼容的輸出20\o"CurrentDocument"1.4.5檔案管理20\o"CurrentDocument"1.5理解profiling結(jié)果21\o"CurrentDocument"中斷延遲的profiling21\o"CurrentDocument"內(nèi)核的profiling22\o"CurrentDocument"解釋callgraph的profiles22\o"CurrentDocument"1.5.4非精確的帶標(biāo)注的源碼22\o"CurrentDocument"1.5.5匯編函數(shù)24\o"CurrentDocument"1.6使用OProfile的實(shí)際例子24\o"CurrentDocument"ctpl的性能分析24OProfile的cons與pros29\o"CurrentDocument"OProfile的主要優(yōu)點(diǎn)29OProfile的主要缺點(diǎn)29\o"CurrentDocument"1.7.3適合使用OProfile的場合30\o"CurrentDocument"OProfile的其他參考資料30\o"CurrentDocument"使用IntelVTune?進(jìn)行性能分析30\o"CurrentDocument"IntelVTuneTM簡介30VTune的功能與適用范圍31VTune的系統(tǒng)需求312.1.3其他可用的VTune資源31VTune的安裝與部署31VTune中的有關(guān)性能調(diào)優(yōu)的名詞與術(shù)語31DataCollector31Project與Activity31DrillingDown322.3使用VTune收集與分析性能數(shù)據(jù)322.3.1使用API收集數(shù)據(jù)322.3.2遠(yuǎn)程收集數(shù)據(jù)322.3.3使用采樣32使用callgraph分析322.3.5靜態(tài)模塊分析322.3.6查看帶Profiling信息的源碼322.3.7使用EventRatios322.4高級(jí)用法32使用TuningAssistant32合并activities322.5使用VTune進(jìn)行性能分析的實(shí)際例子32iknow的fbsmon模塊64位升級(jí)32使用VTune對(duì)ctpl進(jìn)行性能分析322.6VTune的cons與pros32VTune的主要優(yōu)點(diǎn)33VTune的主要缺點(diǎn)332.6.3適合使用VTune的場合332.7其他可以與VTune協(xié)同工作的工具33IntelThreadProfiler333.ANNEX340.文檔說明本文的目標(biāo)在于:a)詳細(xì)描述兩種主要的Profiling工具的用法。b)分析各個(gè)工具的優(yōu)缺點(diǎn)及適用范圍。c)通過實(shí)際的例子說明如何通過此類工具對(duì)代碼進(jìn)行性能調(diào)優(yōu)。d)總結(jié)出一個(gè)合適的流程,作為推薦的在開發(fā)周期中性能調(diào)優(yōu)環(huán)節(jié)中采用的流程。本文不包括對(duì)代碼優(yōu)化方法的介紹與分析。1.使用OProfile進(jìn)行性能分析OProfile的簡介□Profile是一個(gè)工作于2.2/2.4/2.6內(nèi)核的Profiling工具,它支持許多種處理器體系結(jié)構(gòu)。能共分析系統(tǒng)中運(yùn)行的所有模塊:從內(nèi)核到共享庫到二進(jìn)制文件。它運(yùn)行在后臺(tái),以較低的代價(jià)收集信息。這些特性使得它適合于在實(shí)際的系統(tǒng)中分析程序的性能瓶頸。許多CPU支持性能計(jì)數(shù)器,硬件的寄存器可以對(duì)“事件”計(jì)數(shù);例如,緩存命中率或者CPU時(shí)鐘周期。OProfile基于這些重復(fù)發(fā)生的事件進(jìn)行分析。此外,分析時(shí)還記錄PC的值,這些信息將以每個(gè)二進(jìn)制鏡像為單位整合在一起。下面分幾個(gè)部分說明OProfile的相關(guān)信息。1.1.1使用OProfile的動(dòng)機(jī)和約束□Profile適用于下述情況:需要較低的開銷不能使用高侵入性的分析方法需要對(duì)中斷處理進(jìn)行分析需要對(duì)程序及其共享庫進(jìn)行分析需要評(píng)估硬件影響,例如緩存命中需要詳細(xì)的源代碼性能分析注釋需要指令級(jí)分析需要函數(shù)調(diào)用圖分析OProfile不是萬能藥,在下列情況就無法使用OProfile:需要在非2.6/X86系統(tǒng)中分析函數(shù)調(diào)用圖無root權(quán)限需要100%精確的指令分析需要分析函數(shù)調(diào)用數(shù)量或者間隔性的分析API不能容忍任何對(duì)系統(tǒng)的干擾?分析解釋性或動(dòng)態(tài)編譯的代碼,如Java或者Python1.1.2使用OProfile的系統(tǒng)需求內(nèi)核版本□Profile使用的內(nèi)核模塊需要能夠在下列版本的內(nèi)核的系統(tǒng)中成功編譯:2.2.11及以后的版本2.4及2.4.10以后的版本(如果需要引導(dǎo)時(shí)的選項(xiàng)nosmp)2.6及以后的版本(使用內(nèi)置與內(nèi)核的OProfile驅(qū)動(dòng)程序)需要注意的是,在2.2/2.4內(nèi)核上,只支持32位的x86以及IA64架構(gòu)。強(qiáng)烈推薦在2.6內(nèi)核下使用OProfile。在2.4內(nèi)核下,當(dāng)使用電源管理功能或者當(dāng)BIOS沒能正確處理本地APIC時(shí),OProfile可能會(huì)導(dǎo)致系統(tǒng)崩潰。PPC64處理器需要2.6.5以后的內(nèi)核,并且在include/asm-ppc64/processor.h中要有#definePV_970這個(gè)宏存在。針對(duì)某些其他架構(gòu)的處理器,在內(nèi)核方面還有一些額外的約束,具體請(qǐng)參考OProfile實(shí)用手冊(cè)[1]。modutils版本需要2.4.6或更新版本的modutilso處理器體系結(jié)構(gòu)對(duì)于IA32,需要P6架構(gòu)或者Pentium4架構(gòu)的處理器。用市場術(shù)語說,這包括了所有在PentiumPro以及Pentium%Xeon之間的處理器°AMD的Athlon以及Duron處理器也是被支持的。對(duì)于其他IA32架構(gòu)的處理器,只支持RTC模式的分析。對(duì)于2.4內(nèi)核,支持IA-64架構(gòu)但不支持超線程的Pentium4架構(gòu)。對(duì)于2.6內(nèi)核,還支持Alpha處理器、MIPS、ARM、x86-64、sparc64、ppc64、計(jì)時(shí)器模式的PA-RSIC以及S390。多處理器支持完全支持SMP的系統(tǒng)。運(yùn)行時(shí)庫依賴需要下列庫:poptbfdlibertydllibstdc++OProfileGUI□ProfileGUI需要Qt2的支持,Qt3版本應(yīng)該也可以工作。ELF格式的二進(jìn)制文件需要profiling的必須是ELF格式的可執(zhí)行文件,而不是老式的a.out格式。K&R編碼風(fēng)格Ifpossible?1.1.3其他關(guān)于OProfile的可用資源主頁下載匿名CVS:/projects/oprofile.郵件列表/mail/?groupid=169191.1.4安裝OProfile首先需要構(gòu)建OProfile然后再安裝。通常只需要按照下列步驟執(zhí)行即可:./configure->make->makeinstall下面是一些在構(gòu)件時(shí)需要注意的選項(xiàng):--with-linux使用該選項(xiàng)描述內(nèi)核源代碼樹所在的路徑。OProfile使用的模塊需要從對(duì)應(yīng)的內(nèi)核源代碼以及相同的編譯選項(xiàng)構(gòu)建出來。--with-kernel-support在2.6及以后的版本中使用該option表示OProfile的驅(qū)動(dòng)程序由內(nèi)核提供--with-qt-dir/includes/libraries描述Qt的頭文件與庫的路徑。當(dāng)這些選項(xiàng)沒有被設(shè)置時(shí),缺省查找環(huán)境變量$QTDIR--disable-werrorOProfile的開發(fā)版本缺省使用-Werror。該選項(xiàng)關(guān)閉這個(gè)設(shè)置。--disable-optimization在構(gòu)建時(shí)關(guān)閉-O2選項(xiàng),尤其是當(dāng)發(fā)現(xiàn)了OProfile的bug時(shí),使用該選項(xiàng)有助于跟蹤錯(cuò)誤。需要注意的是,如果期望進(jìn)行kernelprofiling,則需要有vmlinux,否則,需要指定—no-vmlinuxoOprofile概述1.2.1開始在開始使用OProfile之前,必須先設(shè)置它。設(shè)置的第一步是指定使用的內(nèi)核鏡像:vmlinux,如不需profilingkernel,則指定--no-vmlinux:opcontrol--vmlinux=/boot/vmlinux-'uname-r'或者:opcontrol--no-vmlinux然后可以準(zhǔn)備啟動(dòng)OProfile的守護(hù)進(jìn)程(oprofiled)來收集采樣數(shù)據(jù):opcontrol--start當(dāng)停止采樣時(shí):opcontrol--shutdown注意,不像gprof,OProfile不需要在代碼中插樁(instrumentation)采樣的數(shù)據(jù)周期性的(或者當(dāng)--shutdown或--dump發(fā)生時(shí))被寫到$SESSION_DIR/samples目錄中(缺省為/var/lib/oprofile/samples)。這些profile文件包括了共享庫、應(yīng)用程序、內(nèi)核以及內(nèi)核模塊。可以通過下述命令清空profile數(shù)據(jù):opcontrol--reset通過opcontrol的--session-dir參數(shù)可以指定存放采樣數(shù)據(jù)的位置:opcontrol--no-vmlinux-session-dir/home/me/tmpsession或者:opcontrol--start-session-dir=/home/me/tmpsession有若干種方法獲得這個(gè)路徑的信息。例如:opreport[--session-dir=dir]同樣,有若干種辦法表示分析結(jié)果。當(dāng)用戶什么也不指定的時(shí)候,OProfile會(huì)選擇缺省的profiling設(shè)置。1.2.2工具小節(jié)OProfile包括下列若干個(gè)工具:ophelp該工具列出所有事件以及簡要的描述opcontrol控制OProfile的數(shù)據(jù)采集過程opreport用來報(bào)告分析結(jié)果opannotate該工具用來生成帶標(biāo)注的源碼、匯編代碼或者源碼/匯編混合代碼。源碼級(jí)的標(biāo)注只有當(dāng)代碼使用-g選項(xiàng)編譯時(shí)才可用。opgprof通過該工具,生成gprof格式的數(shù)據(jù)文件,這些數(shù)據(jù)文件可以通過gprofp查看。oparchive該工具能夠用來收集可執(zhí)行文件、調(diào)試信息以及采樣文件,并且將這些文件打包。這種包是自包含的并且可以復(fù)制到其他機(jī)器上以便于進(jìn)一步的分析。opimport該工具將采樣數(shù)據(jù)庫文件從abi格式轉(zhuǎn)換為本地卡格式。該功能只有當(dāng)在主機(jī)之間移動(dòng)采樣文件時(shí)才有效。1.3控制Profiler使用opcontrol此處將深入討論opcontrol的配置、控制過程。Opcontrol腳本有一個(gè)缺省的設(shè)置,但是用戶可以通過下面列出的各種選項(xiàng)來改變?nèi)笔≡O(shè)置。尤其是當(dāng)硬件支持性能計(jì)數(shù)器時(shí),可以配置這些計(jì)數(shù)器來進(jìn)行有針對(duì)性的profiling。硬件支持的性能計(jì)數(shù)器通常包含多個(gè)并且是可編程的,這些計(jì)數(shù)器可以用來為事件進(jìn)行計(jì)數(shù),例如:MMX操作事件、緩存miss事件等。為每個(gè)計(jì)數(shù)器選定的事件會(huì)在被OProfile收集的數(shù)據(jù)中反映出來:在采樣結(jié)果中最頂部的函數(shù)和二進(jìn)制文件即是代碼中選定事件發(fā)生次數(shù)最多地方。另外,每一個(gè)計(jì)數(shù)器有一個(gè)數(shù)量值:它反映了profile的精度。這個(gè)值越低,采樣越頻繁。一些事件有一個(gè)“掩碼,,,這描述了對(duì)事件的更詳細(xì)的設(shè)置,有關(guān)于運(yùn)行oprofile的平臺(tái)的CPU所支持的事件類型以及掩碼,使用opcontrol--list-events來查看。opcontrol的詳細(xì)選項(xiàng)如下:--init如果需要,載入OProfile的模塊,使得OProfile采樣驅(qū)動(dòng)可用--setup將后面跟隨的所有設(shè)置選項(xiàng)保存在/root/.oprofile/daemonrc中。實(shí)際上該選項(xiàng)不是必須的,指定任意一項(xiàng)設(shè)置選項(xiàng),都包含了該步驟的操作。--status顯示配置信息--start-daemon僅啟動(dòng)oprofiled而不開始采樣。采樣還可以通過--start來啟動(dòng)。本選項(xiàng)有助于將啟動(dòng)oprofiled的開銷隔離在采樣過程之外,以得到更精確的結(jié)果。--start按照--set-up或者/root/.oprofile/daemonrc中描述的配置啟動(dòng)數(shù)據(jù)收集過程。如果此處使用--verbose則在收集過程中會(huì)輸出大量調(diào)試信息。--dump強(qiáng)制守護(hù)進(jìn)程輸出收集到的數(shù)據(jù)。--stop停止數(shù)據(jù)收集。--shutdown停止數(shù)據(jù)收集并且關(guān)閉守護(hù)進(jìn)程。--reset清空當(dāng)前會(huì)話的所有數(shù)據(jù),但保留已保存的會(huì)話。--save=session_name將當(dāng)前會(huì)話中的數(shù)據(jù)保存在session_name中。--deinit關(guān)閉守護(hù)進(jìn)程,寫在OProfile的內(nèi)核模塊以及oprofilefs。--list-events列出當(dāng)前CPU支持的事件以及掩碼。還有其他一些可用的選項(xiàng),其中,只有--vmlinux或者--no-vmlinux是必須的:--buffer-size=NUM內(nèi)核緩沖區(qū)中的采樣數(shù)。當(dāng)使用2.6內(nèi)核時(shí),此值改變時(shí)buffer-watershed也要隨之改變--cpu-buffer-size=NUM內(nèi)核中每CPU緩沖的采樣數(shù)(只在2.6內(nèi)核中有效)。--event=[eventspec]使用給定的性能計(jì)數(shù)器事件采樣。--session-dir=PATH使用指定的采樣數(shù)據(jù)庫路徑,而不是缺省的/var/lib/oprofile--separate=[none,lib,kernel,thread,cpu,all]缺省的,每次采樣保存在一個(gè)單獨(dú)的文件中。然而,通過指定上述選項(xiàng),可以將采樣數(shù)據(jù)分別存放在不同的文件中,細(xì)節(jié)如下:lib按照庫分隔進(jìn)行profilekernel按照內(nèi)核與內(nèi)核模塊分隔進(jìn)行profilethread按照每個(gè)線程與任務(wù)分隔進(jìn)行profilecpu按照每個(gè)CPU分隔進(jìn)行profileall所有選項(xiàng)都分隔注意,--separate=kernel開啟則--separate=lib會(huì)自動(dòng)關(guān)閉。當(dāng)使用--separate=kernel時(shí),當(dāng)前執(zhí)行的任務(wù)中的硬件終端、軟中斷以及其他異步內(nèi)核上下文都會(huì)被采樣。這意味著你將看到很多看上去毫無意義的采樣結(jié)果,例如bash。使用--separate=thread是,你會(huì)發(fā)現(xiàn),運(yùn)行一會(huì)兒oprofile則有大量的文件被創(chuàng)建,該選項(xiàng)更適合于短會(huì)話的采樣或者使用了鏡像過濾時(shí)的采樣。--callgraph=#DEPTH開啟調(diào)用圖采樣,且深度為最大深度。使用0則關(guān)閉調(diào)用圖采樣。--image=image,[image]|"all"鏡像過濾設(shè)置。如果指定一個(gè)或者多個(gè)二進(jìn)制文件的絕對(duì)路徑,OProfile將只生成指定的二進(jìn)制文件的采樣結(jié)果。這個(gè)選項(xiàng)對(duì)過濾掉不關(guān)注的二進(jìn)制文件的采樣信息特別有效,尤其是當(dāng)與--separate=thread選項(xiàng)一起使用時(shí),更是如此。--vmlinux=file指定內(nèi)核鏡像--no-vmlinux采樣不使用內(nèi)核鏡像IntelCPU性能計(jì)數(shù)器的設(shè)置如果CPU是P4架構(gòu),則下面的命令說明了如何按照CPU時(shí)鐘以及內(nèi)存訪問進(jìn)行采樣:「;opcontrol--event=CPUCLKUNHALTED:400000--event=DATAMEMREFS:10000opcontrol--vmlinux=/boot/2.6.0/vmlinuxopcontrol--startRTC模式使用ophelpr查看當(dāng)前平臺(tái)使用的模式,如果是RTC模式,則用如下方式啟動(dòng):Iophelp-rCPUwithRTCdeviceiopcontrol--vmlinux=/boot/2.4.13/vmlinux--event=RTC_INTERRUPTS:1024i—opcontrol--start.3單獨(dú)啟動(dòng)oprofiled守護(hù)進(jìn)程當(dāng)使用2.6內(nèi)核時(shí),可以使用--start-daemon來避免啟動(dòng)采樣器的時(shí)候影響結(jié)果。Iopcontrol--vmlinux=/boot/2.6.0/vmlinuxIopcontrol--start-daemonimy_favourite_benchmark--initopcontrol--start;my_favourite_benchmark-run;opcontrol--stop.4分隔對(duì)庫與內(nèi)核的采樣如果想采樣OProfile自身,包括它使用的內(nèi)核驅(qū)動(dòng)程序以及所有的共享庫,可以做如下操作:Iopcontrol--separate=kernel-vmlinux=/boot/2.6.0/vmlinuxopcontrol--startimy_favourite_stress_test--runi———opreport-l-p/lib/modules/2.6.0/kernel/usr/local/bin/oprofiled有時(shí)將采樣的數(shù)據(jù)按照不同的時(shí)間段分散保存是很有必要的做法,可以通過下面的操作實(shí)現(xiàn)這個(gè)目標(biāo):I#opcontrol=save=dir描述性能計(jì)數(shù)器事件通過--event選項(xiàng)來指定采樣時(shí)使用的性能計(jì)數(shù)器事件及具體的參數(shù)。使用--event-default則使用缺省的性能計(jì)數(shù)器事件??梢允褂枚鄠€(gè)性能計(jì)數(shù)器事件。OProfile按照需要分配硬件計(jì)數(shù)器。但是有些組合是不被CPU支持的。運(yùn)行opcontrol--list-event能夠列出所有事件的詳細(xì)描述。事件描述的格式如下:name:count:unitmask:kernel:user具體說明請(qǐng)參考OProfile手冊(cè)。使用oprof_startoprof_start提供了一個(gè)啟動(dòng)分析器的簡便的方式。實(shí)際上它只是opcontrol的一個(gè)wrapper。它不能做opcontrol支持的之外的事情。1.3.3配置細(xì)節(jié)有關(guān)OProfile的工作模式,需要注意的是對(duì)于新的CPU(例如基于Core架構(gòu)的Xeon),OProfile沒有提供完整的硬件性能計(jì)數(shù)器的支持,在這種情況下,在2.4內(nèi)核中只有RTC模式可用,在2.6內(nèi)核中,只有時(shí)鐘中斷模式可用。硬件性能計(jì)數(shù)器CPU的硬件性能計(jì)數(shù)器在其體系結(jié)構(gòu)手冊(cè)中有描述。概要的說,通過對(duì)計(jì)數(shù)器設(shè)置的溢出值,當(dāng)計(jì)數(shù)器的值達(dá)到設(shè)置的值從而發(fā)生溢出時(shí),產(chǎn)生一個(gè)中斷,從而達(dá)到采樣的目的。這也是OProfile的基本工作機(jī)制。中斷被提交的方式是NMI,所以在內(nèi)核中屏蔽中斷也不會(huì)對(duì)采樣產(chǎn)生影響。當(dāng)中斷處理程序被調(diào)用時(shí),當(dāng)前的PC值以及當(dāng)前任務(wù)被保存到profiling結(jié)構(gòu)中,這使得發(fā)生溢出的事件被附加在二進(jìn)制文件的一個(gè)特定的匯編指令中,守護(hù)進(jìn)程從內(nèi)核接收這些數(shù)據(jù),并寫到采樣的數(shù)據(jù)文件中。使用諸如CPU_CLK_UNHALTED或者INST_RETIRED事件,我們可以使用溢出數(shù)量估計(jì)代碼中每一個(gè)部分所消耗的時(shí)間。此外可以采用其他事件采樣感興趣的數(shù)據(jù)例如緩存命中率。然而有一些需要注意的地方:在Intel的手冊(cè)上列出了一些問題。在性能計(jì)數(shù)器溢出發(fā)生一個(gè)中斷請(qǐng)求與該請(qǐng)求被deliver之間有一個(gè)延時(shí),這可能對(duì)結(jié)果小有影響-這意味著不能再指令級(jí)別精確的依賴采樣結(jié)果。如果使用一個(gè)“事件模式”的計(jì)數(shù)器如緩存計(jì)數(shù)器,當(dāng)一次計(jì)數(shù)發(fā)生時(shí)不一定意味著發(fā)生了一個(gè)對(duì)應(yīng)的事件,只是這暗示著在當(dāng)前對(duì)應(yīng)的一條指令或幾條指令臨近發(fā)生了計(jì)數(shù)器溢出。每個(gè)事件有幾個(gè)配置參數(shù)。首先是一個(gè)unitmask:這描述了具體的計(jì)數(shù)事件;接下來是一個(gè)數(shù)量值,在下面有說明;第三個(gè)是一個(gè)標(biāo)志,用來設(shè)置在內(nèi)核還是用戶空間增加計(jì)數(shù)??梢詫?duì)每一個(gè)計(jì)數(shù)器分別進(jìn)行這些參數(shù)的配置。每一次溢出事件之后,計(jì)數(shù)器會(huì)被重初始化。這也意味著,計(jì)數(shù)器的溢出值越大,采樣就越粗糙,同時(shí)開銷也小。反之則采樣就越精細(xì),但開銷增大。為溢出值選擇一個(gè)合適的參數(shù)是很難的,這依賴于具體的事件。通常要在獲得足夠的采樣數(shù)與盡量低的開銷兩者間小心權(quán)衡。OProfile的RTC模式RTC模式只能應(yīng)用于2.22.4內(nèi)核中,此處不介紹,細(xì)節(jié)可參考OProfile手冊(cè)。OProfile的時(shí)鐘中斷模式時(shí)鐘中斷模式僅工作在2.6內(nèi)核中。當(dāng)CPU不支持硬件性能計(jì)數(shù)器時(shí),OProfile將回退為使用時(shí)鐘中斷模式。和RTC模式一樣,當(dāng)中斷被disable時(shí),不能進(jìn)行采樣。對(duì)于這個(gè)模式,沒有任何配置參數(shù)。1.4獲得結(jié)果Profiler開始運(yùn)行之后,最重要的事情無疑就是收集數(shù)據(jù)了。有時(shí),OProfile為了盡量降低開銷,會(huì)盡量延遲或者避免想profiler寫采樣數(shù)據(jù)。這種情況尤其會(huì)發(fā)生在負(fù)載很低的主機(jī)上。此時(shí)可以使用opcontroldump來強(qiáng)制輸出數(shù)據(jù)。獲得數(shù)據(jù)之后,接下來的任務(wù)交給opreport、opannotate或者opgprof。ProfileSpecificationProfilespecification描述了使用opreport需要follow的一些準(zhǔn)則。采樣的結(jié)果包含很多profiles,在使用opreport查看結(jié)果時(shí),需要按照profile的spec來指定具體的profile。其格式為:name:value[,value]。例如,如果想要獲得一個(gè)包含了/bin/myprog1與/bin/myprog2的符號(hào)的匯總信息,可以這樣使用opreport:opreport-limage:/bin/myprog1,/bin/myprog2作為一個(gè)特例,實(shí)際上不需要指定image:部分:所有命令行后面的內(nèi)容都被假定為image:名字。類似的,如果沒有指定session:則默認(rèn)為session:current。對(duì)于再后面的,用逗號(hào)分隔的參數(shù)支持通配符,例如:opreport-limage:/bin/\*例子在名字為stresstest的session中,對(duì)于事件DATA_MEM_REFS查看對(duì)所有profile的鏡像匯總:#opreportsession:stresstestevent:DATA_MEM_REFS對(duì)于名字為test_sym53c8xx,9xx,查看符號(hào)匯總:(注意,在image后使用轉(zhuǎn)義字符)I#opreport-l,/test/test_sym53c8xx\,9xxI—在test目錄中查看除了boring-test之外的所有二進(jìn)制文件的鏡像匯總:#opreport-l./test/test_sym53c8xx\,9xx進(jìn)行差分分析:I#opreport-l/bin/bash{archive:./orig}{archive:./new}對(duì)當(dāng)前的會(huì)話執(zhí)行差分分析:I#opreport-l/bin/bash{archive:./orig}{}參數(shù)archive:archivepath指向通過oparchive生成的archive文件的路徑。缺省為archive:session:sessionlist逗號(hào)分隔的會(huì)話名稱。缺省為session:currentSession-exclude:sessionlist要排除的會(huì)話名稱,可以用逗號(hào)分隔多個(gè)名字。image:imageList逗號(hào)分隔的鏡像名列表。每個(gè)項(xiàng)目可以是相對(duì)路徑、帶通配符的名字或者完整路徑。image-exclude:imageList與image相同,但是exclude指定的鏡像lib-image:imageList與image相同,但是只報(bào)告那些特定的二進(jìn)制鏡像(應(yīng)用程序)。該選項(xiàng)只在當(dāng)使用了--separate的時(shí)候有效。lib-image-exclude:imageList與lib-image相同,但是exclude指定的鏡像event:eventList報(bào)告指定的事件名字相關(guān)的profile結(jié)果。unit-mask:maskList報(bào)告時(shí)需要匹配的事件的unitmask值。cpu:cpuList只考慮指定CPU上的profile,CPU編號(hào)從0開始。tgid:pidList報(bào)告指定任務(wù)組的profile結(jié)果。該選項(xiàng)只有在使用按照每個(gè)進(jìn)程分隔的profiling時(shí)有意義。tid:tidList只報(bào)告指定的線程的profile。在當(dāng)前主流的線程庫中,一個(gè)進(jìn)程中的所有線程共享同樣的任務(wù)組ID,但是線程ID不同。該選項(xiàng)可與tgid選項(xiàng)一起使用去描述指定進(jìn)程中的指定線程。定位與管理二進(jìn)制鏡像所有session的采樣文件都保存在$SESSION_DIR/samples/路徑中,缺省的位置%/var/lib/oprofile/samples潞徑下。這些文件能夠生成易讀的格式的報(bào)告。當(dāng)OProfile無法找到需要的二進(jìn)制鏡像時(shí),可以使用--image-path選項(xiàng)傳遞一個(gè)逗號(hào)分隔的路徑列表用來搜索二進(jìn)制鏡像。需要注意的是,如果二進(jìn)制鏡像在采樣之后被改動(dòng)了,用戶將無法獲得有效的基于符號(hào)表的信息。如果二進(jìn)制鏡像改變了,用戶可以選擇備份舊的采樣信息,以用來與未來的新的采樣信息進(jìn)行比較。當(dāng)無法獲得結(jié)果時(shí)該怎么辦如果在嘗試獲得報(bào)告的輸出是遇到下面的消息:■error:nosamplefilesfound:profilespecificationtoostrict這表明按照指定的條件,在采樣的數(shù)據(jù)中未發(fā)現(xiàn)能匹配的結(jié)果信息,這可能是由一下幾種原因?qū)е碌模浩磳戝e(cuò)誤寫錯(cuò)了鏡像文件的名字。Profiler未運(yùn)行確認(rèn)當(dāng)運(yùn)行應(yīng)用程序時(shí),OProfile已經(jīng)運(yùn)行了。二進(jìn)制文件未運(yùn)行足夠長時(shí)間OProfile是一個(gè)統(tǒng)計(jì)分析工具,無法保證在短時(shí)間運(yùn)行的程序中獲得足夠的采樣??梢酝ㄟ^在性能計(jì)數(shù)器中使用盡可能小的溢出值,以在單位時(shí)間內(nèi)獲得盡可能多的采樣。二進(jìn)制文件的大部分時(shí)間被其調(diào)用的庫消耗如果二進(jìn)制程序在其自身幾乎未有任何開銷,而在其調(diào)用的庫中開銷巨大的時(shí)候,是無法從二進(jìn)制文件本身獲得profile結(jié)果的。可以使用opcontrol--separate=lib來確認(rèn)這種情況是否發(fā)生。Spec太嚴(yán)格例如,指定了并不存在的任務(wù)組id:tgid:3333。二進(jìn)制文件沒發(fā)生任何指定的事件當(dāng)使用性能計(jì)數(shù)器事件時(shí),如果指定的事件沒有發(fā)生,則不會(huì)有任何結(jié)果。例如指定了MMX相關(guān)的事件時(shí),如果程序中沒有相關(guān)操作,則無法獲得任何結(jié)果。1.4.2.鏡像與符號(hào)的結(jié)果匯總(使用opreport)□Profile中用來報(bào)告采樣結(jié)果的工具opreport能夠成采樣數(shù)據(jù)中按照需要獲取對(duì)應(yīng)格式的結(jié)果數(shù)據(jù)。它生成兩種類型的數(shù)據(jù):按照鏡像的結(jié)果匯總以及按照符號(hào)的結(jié)果匯總。鏡像的結(jié)果匯總列出了采樣過程中涉及到的單個(gè)二進(jìn)制文件(應(yīng)用程序以及相應(yīng)的庫)各自的結(jié)果。符號(hào)結(jié)果匯總則提供了每個(gè)符號(hào)的profile數(shù)據(jù)。下面的例子展示了整個(gè)系統(tǒng)的鏡像結(jié)果匯總:注:數(shù)據(jù)來自O(shè)Profile手冊(cè)TOC\o"1-5"\h\z「-III$opreport--long-filenamesCPU:PIII,speed863.195MHz(estimated)CountedCPU_CLK_unhaltedevents(clocksprocessorisnothalted)withaunitmaskof0x00(Nounitmask)count23150iii90589859.7415/usr/lib/gcc-lib/i386-redhat-linux/3.2/cc1plus21432014.1338/boot/2.6.0/vmlinux1034506.8222/lib/i686/libc-2.3.2.so601603.9674/usr/local/bin/madplayTOC\o"1-5"\h\ziii317692.0951/usr/local/oprofile-pp/bin/oprofilediii265501.7509/usr/lib/libartsflow.so.1.0.0239061.5765/usr/bin/as187701.2378/oprofile155281.0240/usr/lib/qt-3.0.5/lib/libqt-mt.so.3.0.5!ii119790.7900/usr/X11R6/bin/XFree86ii113280.7471/bin/bash如果在opreport命令中指定了--symbols,就能看到整個(gè)系統(tǒng)中所有運(yùn)行的鏡像的符號(hào)結(jié)果匯總。用戶可以將不關(guān)注的部分的profile結(jié)果過濾掉,例如,下面的例子是OProfile守護(hù)進(jìn)程的profile數(shù)據(jù),需要注意的是這個(gè)結(jié)果是在采樣是使用了--separate=kernel得到的:$opreport-l'whichoprofiled'2>/dev/null|moreiiCPU:PIII,speed863.195MHz(estimated)CountedCPU_CLK_unhaltedevents(clocksprocessorisnothalted)withaunitmaskof10x00(Nounitmask)count231501.vma1samples%imagename1symbolnamei10804be101497128.1993oprofiledodb_insert0804afdc714413.4564oprofiledpop_buffer_valuec01daea0611311.5144vmlinux—copy_to_user_ll0804b060i28165.3042oprofiledopd_put_sample!10804b4a021474.0441oprofiled1opd_process_samples10804acf418553.4941oprofiledopd_put_image_sample0804ad8417663.3264oprofiledopd_find_image0804a5ec110842.0418oprofiledopd_find_module0804ba5c7411.3957oprofiled1odb_hash_add_nodei上面兩種是比較常用的查看結(jié)果報(bào)告的方法,此外,opreport還可以支持更多的功能。合并分隔的profiles如果已經(jīng)在采樣時(shí)使用T--separate=^項(xiàng),在session中對(duì)于某一個(gè)特定的二進(jìn)制文件,可能存在多個(gè)單獨(dú)的profile。通常這些profile是被分開保存的。但有時(shí)為了獲取更有意義的結(jié)果,也需要將分開保存的profile再合并起來,--merge選項(xiàng)就能夠支持這種意圖。多結(jié)果并行如果在采樣時(shí)指定了多個(gè)事件,缺省情況下的輸出是每個(gè)時(shí)間單獨(dú)為一組進(jìn)行輸出的??梢酝ㄟ^event:來限制輸出哪些事件的profile數(shù)據(jù)。Callgraph輸出當(dāng)使用opcontrol--callgraph選項(xiàng)的時(shí)候,可以得到函數(shù)調(diào)用關(guān)系的結(jié)果??紤]下面的例子程序:TOC\o"1-5"\h\z|I#include<string.h>|||#include<stdlib.h>i1i#include<stdio.h>i'i'i'i#definesize500000istaticintcompare(constvoid*s1,constvoid*s2)(i1i1returnstrcmp(s1,s2);i1i}'i'ii|istaticvoidrepeat(void)(1inti;i1ichar*strings[SlZE];icharstr[]="abcdefghijklmnopqrstuvwxyz";1;'iifor(i=0;i<size;++i)(i1i1strings[i]=strdup(str);iistrfry(strings[i]);}'i1i1qsort(strings,SIZE,sizeof(char*),compare);i1i}'i'iiintmain()(iwhile(1)當(dāng)以--callgraph選項(xiàng)運(yùn)行時(shí),OProfile會(huì)在采樣的時(shí)候記錄函數(shù)棧。opreport--callgraph按照每個(gè)函數(shù)一個(gè)單位進(jìn)行輸出:1samples%imagename1symbolname1970.1548cgimain127036i99.8452cgrepeat8459042.5084libc-2.3.2.sostrfry8459066.4838libc-2.3.2.sostrfry[self]3916930.7850libc-2.3.2.sorandom_r3475ii_2.7312libc-2.3.2.so1—i686.get_pc_thunk.bxi_i其中,沒有縮進(jìn)的行是需要關(guān)注的函數(shù):strfry()。在未縮進(jìn)的行的上方,是調(diào)用了函數(shù)strfry的函數(shù)。例如,函數(shù)repeat調(diào)用了strfry。采樣數(shù)與百分比的值表示當(dāng)采樣時(shí),在棧中發(fā)現(xiàn)該函數(shù)的次數(shù)。百分比與所有其他調(diào)用者相關(guān)。需要這一得是,采樣數(shù)不是函數(shù)調(diào)用次數(shù)。在未縮進(jìn)行的下方,是strfry函數(shù)調(diào)用的函數(shù)。很明顯能看到,strfry調(diào)用了random_r函數(shù)。根據(jù)標(biāo)示的信息,能夠知道,在函數(shù)strfry中,66.48%的操作(時(shí)間或者是其他因素,具體取決于工作模式)為strfry自身的代碼占用,30.78%被它調(diào)用的random_r占用,其他2.7312%被__i686.get_pc_thunk.bx占用。使用opreport對(duì)profile進(jìn)行diff很多時(shí)候,我們相比較兩個(gè)profiles的差異。例如,當(dāng)分析一個(gè)程序的性能時(shí),需要修改代碼之后再檢查修改是否有效。這通過下面的操作實(shí)現(xiàn):TOC\o"1-5"\h\zII[$opreport<share-spec>(<first-profile>}(<second-profile>}:需要注意的是,在大括號(hào)與尖括號(hào)之間要留有空格。使用這一特性的典型方式是通過操作使用oparchive對(duì)profile進(jìn)行打包后的文檔與當(dāng)前的session進(jìn)行比較。下面是個(gè)例子:■;$./a1I$oparchive-oorig./a$opcontrol-resetieditcodeandrecompilea1i$./anowcomparethecurrentprofileofawiththearchivedprofile1$opreport-xl./a(archive:./orig}(}CPU:PIII,speed863.233MHz(estimated)iCountedCPU_CLK_unhaltedevents(clocksprocessorisnothalted)withaiiunitmaskof0x00(Nounitmask)count100000匿名的可執(zhí)行mapping有些程序是動(dòng)態(tài)被編譯成機(jī)器碼而執(zhí)行的,例如java程序,它們無法映射為一個(gè)ELF格式的文件。opreport對(duì)此有一個(gè)基本的支持,例如:|$opreport/usr/jre1.5.0/bin/javaCPU:PIII,speed863.195MHz(estimated)CountedCPU_CLK_unhaltedevents(clocksprocessorisnothalted)withaunitmaskof0x00(Nounitmask)count100000iicpu_clk_unhalt...|samples!%|27344100.000javacpu_clk_unhalt...|samples!%|2723699.605anon(tgid:12135range:0xb2cb8000-0xb2e80000)1080.3949java當(dāng)前還無法支持對(duì)這樣的代碼獲得基于符號(hào)的匯總。需要注意的是,由于這樣的映射與被調(diào)用的二進(jìn)制文件無關(guān),將總是被作為一個(gè)單獨(dú)的鏡像別顯示,即使使用-separate=none也是如此。同樣,它們不會(huì)被--merge選項(xiàng)影響。XML格式輸出--xml選項(xiàng)用來生成XML格式的輸出。需要主義的是,--sort選項(xiàng)與--xml選項(xiàng)是不兼容的。百分比信息也不會(huì)再XML格式的輸出中顯示。在XML格式的輸出中,文件的路徑總是顯示為全路徑,所以--long-filename也不是必須的。選項(xiàng)--details將導(dǎo)致結(jié)果XML中包含所有的采樣數(shù)據(jù),這會(huì)導(dǎo)致生成的XML文件尺寸巨大。opreport的選項(xiàng)--accumulated/-a在符號(hào)列表中累計(jì)采樣數(shù)與百分比--callgraph/-c顯示函數(shù)調(diào)用信息--debug-info/-g顯示每一個(gè)符號(hào)的源文件名及行號(hào)--details/-d對(duì)選定的符號(hào)顯示每個(gè)指令的細(xì)節(jié)。對(duì)于無符號(hào)信息的二進(jìn)制文件,顯示其在鏡像文件中的偏移的VMA值--exclude-dependent/-x只有當(dāng)使用了--separate選項(xiàng)時(shí)有效。不包括應(yīng)用程序相關(guān)的庫、內(nèi)核模塊以及內(nèi)核數(shù)據(jù)。--exclude-symbols/-e[symbols]排除給定的逗號(hào)分隔的列表中的所有符號(hào)。--global-percent/-%使用全局百分比--image-path/-p[paths]在指定的,用逗號(hào)分隔的路徑列表中查找二進(jìn)制鏡像。--include-symbols/-I[symbols]只包含給定的用逗號(hào)分隔的符號(hào)列表中的符號(hào)。--long-filenames/-f在輸出的信息中,文件名字用全路徑名的形式顯示。--merge/-m[lib,cpu,tid,tgid,unitmask,all]將所有分離統(tǒng)計(jì)的結(jié)果合并。--no-header不輸出profiling參數(shù)的頭部細(xì)節(jié)信息。--outut-file/-o[file]輸出至指定的文件。--reverse-sort/-r對(duì)結(jié)果反向排序。--show-address/-w對(duì)符號(hào)顯示VMA地址。--threshold/-t[percentage]過濾結(jié)果信息,不顯示采樣百本比低于指定的百分比的Profile的信息。其他參數(shù)請(qǐng)看靠OProfile手冊(cè)。1.4.3輸出帶標(biāo)注的源碼opannotate工具能夠生成帶profile信息的源碼文件或者匯編代碼文件,也可以將源碼與匯編碼混合輸出。如果想查看源碼,程序要有調(diào)試信息,也就是需要用GCC的-g選項(xiàng)進(jìn)行編譯。而如果二進(jìn)制文件沒有包括足夠的調(diào)試信息,則無法生成有效的帶有profile信息的源碼,此時(shí)可以通過--assembly選項(xiàng)來獲得帶標(biāo)注的匯編代碼。使用--source能夠?qū)?biāo)注的源碼輸出至一個(gè)單獨(dú)的文件,也可以聯(lián)同—assembly一起使用來生成源碼/匯編語句混合的代碼。也可以將帶標(biāo)注的代碼按照原來的結(jié)構(gòu)輸出至一個(gè)目錄中:TOC\o"1-5"\h\z|I$opannotate--source--output-dir=annotated/usr/local/oprofile-pp/bin/oprofiled$Isannotated/home/moz/src/oprofile-pp/daemon/iiopd_cookie.hopd_image.copd_kernel.copd_sample_files.coprofiled.c!I實(shí)際的結(jié)果如下::staticuint64_tpop_buffer_value(structtransient*trans)115101.9661:(/*pop_buffer_valuetotal:8990115.3566*/一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一_1:uint64_tval;.i10227:1.7469::::if(!trans->remaining)(fprintf(stderr,"BUG:poppingexit(EXIT_FAILURE);}1111emptybuffer!\n");iiiii2281229610454???::0.3896:0.3922::1.7857:}val=get_buffer_value(trans->buffer,trans->remaining--;trans->buffer+=kernel_pointer_size;returnval;0);11111111111每行的第一個(gè)數(shù)字是該行代碼的采樣數(shù),第二個(gè)是百分比數(shù)。定位源文件opannotate當(dāng)然需要對(duì)應(yīng)二進(jìn)制文件的源碼文件,可以通過--search-dirs選項(xiàng)來指定尋找源碼的路徑信息。有時(shí)可執(zhí)行文件中保存的是到源碼文件的相對(duì)路徑,此時(shí)使用--base-dirs選項(xiàng)給oprofile更多的信息去查找源碼文件所在位置。例如,假設(shè)我們有一個(gè)二進(jìn)制文件,是由/tmp/build/libfoo/foo.c生成的,并且源碼樹與在/home/user/libfoo相對(duì)應(yīng)。此時(shí)可以按照如下的方式操作:TOC\o"1-5"\h\z|I小…-一'$opannotate-source\I--base-dirs=/tmp/build/libfoo/\|I--search-dirs=/home/user/libfoo/\|I--output-dir=annotated//lib/libfoo.so--assembly/-a輸出帶profile信息的匯編代碼。--base-dirs/-b[paths]/指定尋找目標(biāo)源代碼的原始路徑--exclude-symbols/-e[symbols]在結(jié)果中不顯示指定symbolo--image-path/-p[paths]指定二進(jìn)制鏡像的路徑其他的選項(xiàng)請(qǐng)參考OProfile手冊(cè)。1.4.4即rof兼容的輸出opgprof能夠輸出被gprof兼容的結(jié)果。I$opgprof'whichoprofiled'#generatesgmon.outfile$gprof-p'whichoprofiled'|headiFlatprofile.iiEachsamplecountsas1samples.%<cumulativeselfselftotaltimesamplessamplescallsT1/callT1/callname33.13206237.00206237.00odb_insert22.67347386.00141149.00pop_buffer_value9.56406881.0059495.00opd_put_sample7.34452599.0045718.00opd_find_image7.19497327.0044728.00opd_process_samples一些常用的opgprof選項(xiàng):--image-path/-p[paths]查找二進(jìn)制文件的路徑,可以是多個(gè),以逗號(hào)分隔。--output-filename/-o[file]輸出至指定文件--threshold/-t[percentage]輸出項(xiàng)目的閾值設(shè)置。其他選項(xiàng)請(qǐng)參考OProfile手冊(cè)。1.4.5檔案管理使用oparchive工具來對(duì)指定的采樣信息、可執(zhí)行文件、調(diào)試信息打包成一個(gè)檔案文件:I:$oparchivep/tmp/current_data該操作將當(dāng)前會(huì)話中的信息打包保存在/tmp/current_data中。1.5理解profiling結(jié)果在解釋profiling結(jié)果時(shí),需要記住:在真實(shí)的環(huán)境中profile在不同的場景中profile盡可能進(jìn)行長時(shí)間的profile不要太信任profile數(shù)據(jù)還要記住,不能指望指令級(jí)profiling是完全精確的。1.5.1中斷延遲的profiling這里有一個(gè)例子說明了中斷被deliver的延遲是如何影響profiling數(shù)據(jù)的可靠性的。這個(gè)例子大概是最糟糕的情況的例子了:這些問題幾乎很少發(fā)生。doublefun(doublea,doubleb,doublec){doubleresult=0;for(inti=0;i<10000;++i)(:!result+=a;result*=b;:result/=c;}returnresult;}此處,for循環(huán)的最后一個(gè)指令的執(zhí)行代價(jià)很高,并且也希望結(jié)果能反映出這一點(diǎn),但是,根據(jù)opannotate輸出的匯編代碼(循環(huán)體內(nèi)的部分):「■II$opannotate-a-t10./a.out8815.38%:8048337:fadd%st(3),%st488.391%:8048339:fmul%st(2),%st6811.88%:804833b:fdiv%st(1),%st36864.33%:804833d:inc%eax:804833e:cmp$0x270f,%eax:8048343:jle8048337可以看到,實(shí)際上除法操作并沒有占太多的百分比,相反,大部分開銷是在804833d的代碼:inc%eax消耗的。可以想象這是不準(zhǔn)確的。這個(gè)問題是由于x86處理器的硬件導(dǎo)致的。性能計(jì)數(shù)器溢出而導(dǎo)致一個(gè)中斷請(qǐng)求被發(fā)出,但硬件會(huì)延遲NMI中斷:x86的硬件是同步的(在一個(gè)指令執(zhí)行期間不會(huì)被中斷處理打斷),IRQ發(fā)生的時(shí)候也有一個(gè)延遲,并且在x86的亂序執(zhí)行模型中,多個(gè)執(zhí)行單元也會(huì)導(dǎo)致一些問題。下面是同一段代碼:$opannotate-s-t10./a.outi-:doublefun(doublea,doubleb,doublec):(/*_Z3fundddtotal:572100.0%*/i:doubleresult=0;36864.33%:for(inti=0;i<10000;++i)(結(jié)論就是:不能信任循環(huán)中最后一個(gè)語句的采樣結(jié)果。尤其是當(dāng)編譯器生成的循環(huán)的最后一個(gè)指令是復(fù)雜的、消耗的過多CPUclock的操作時(shí),更是如此。這樣的情況對(duì)于分支操作也同樣存在。還需要記住的是,采樣也有可能被延遲。內(nèi)核的profiling對(duì)于內(nèi)核的profiling,請(qǐng)參考OProfile手冊(cè)。解釋callgraph的profiles有時(shí)callgraph的profile結(jié)果可能會(huì)與預(yù)期有所不同,此時(shí),首先要做的就是檢查目標(biāo)二進(jìn)制文件在編譯時(shí)是否開啟了frame指針(如果二進(jìn)制文件在編譯時(shí)使用了編譯器的-fomit-frame-pointer選項(xiàng),則無法獲得有意義的結(jié)果)。需要進(jìn)一步注意的是,gcc缺省是沒有開啟frame指針的。Linux內(nèi)核缺省也是沒有開啟frame指針的。通常,可能會(huì)發(fā)現(xiàn)一個(gè)函數(shù)的調(diào)用者實(shí)際上并沒有直接調(diào)用該函數(shù),例如函數(shù)a調(diào)用了b,而b調(diào)用了c,此時(shí),在profile結(jié)果中可能看到a調(diào)用了c。這是由于在采樣的時(shí)候,是在函數(shù)c的最開始/最結(jié)尾的部分,此時(shí)新函數(shù)的frame還沒有被創(chuàng)建或者已經(jīng)結(jié)束,所以看起來就像是a直接調(diào)用了c。與OProfile的其他部分相同,callgraph的profiling使用統(tǒng)計(jì)方法,這意味著有時(shí)棧軌跡會(huì)被截?cái)?,或者部分是錯(cuò)誤的。在查看結(jié)果是需要牢記這一點(diǎn)。1.5.4非精確的帶標(biāo)注的源碼優(yōu)化的副作用在編譯器對(duì)代碼進(jìn)行優(yōu)化的時(shí)候,會(huì)引入很多tricks,使得調(diào)試信息與二進(jìn)制的代碼無法完全對(duì)應(yīng)。內(nèi)聯(lián)函數(shù)有時(shí),一個(gè)函數(shù)實(shí)際上被采樣的數(shù)量與annotated的代碼所顯示的采樣的數(shù)目可能不同,此時(shí)極有可能是由于函數(shù)內(nèi)部調(diào)用了inline的函數(shù)。實(shí)際的例子可以參考OProfile手冊(cè)的

節(jié)(/doc/debug-info.htm)。此時(shí),相差的采樣數(shù)會(huì)在源碼中定義了inline函數(shù)的地方被顯示。不精確的行號(hào)信息取決于具體的編譯器,用戶可能會(huì)遇到這樣的問題:對(duì)于下面的代碼:structbig_object(inta[500];};intmain(){big_objecta,b;for(inti=0;i!=1000*1000;++i)b=a;return0;}在gcc3.0.4中編譯時(shí),使用opannotate生成的源碼顯然是不精確的::intmain()/*maintotal:7871100%*/big_objecta,b;for(inti=0;i!=1000*1000;++i)b=a;7871100%:7871100%::}這是由于IRQ延時(shí)造成的。此時(shí),使用opannotateas能夠獲得有益的信息:intmain(){big_objecta,b;:for(inti=0;i!=1000*1000;++i):80484c0:push%ebp:80484c1:mov%esp,%ebp:80484c3:sub$0xfac,%esp:80484c9:push%edi1:80484ca:push%esi:80484cb:push%ebx:b=ia;:80484cc:lea0xfffff060(%ebp),%edx1:80484d2:lea0xfffff830(%ebp),%eax:80484d8:mov$0xf423f,%ebx:80484dd:lea0x0(%esi),%esi:return0;ii30.03811%:80484e0:mov%edx,%edi1:80484e2:mov%eax,%esi這樣就知道,所有的采樣都是正確的,但是行號(hào)信息有誤。要注意的是,在編譯器對(duì)代碼進(jìn)行優(yōu)化時(shí)想要保持精確的調(diào)試信息是很困難的,所以這個(gè)結(jié)果并不令人驚訝。調(diào)試信息的精確性還取決于使用的binutils的版本。1.5.5匯編函數(shù)匯編器通常情況下是不會(huì)自動(dòng)生成調(diào)試信息的。但是可以手工添加調(diào)試信息。具體做法請(qǐng)參考OProfile手冊(cè)(/doc/symbol-without-debug-info.htm)。1.6使用OProfile的實(shí)際例子首先確定CPU是否支持性能計(jì)數(shù)器模式:Iophelp-rICPUwithtimerinterrupti:0:GenuineIntel:6:15::0:GenuineIntel:6:15:Intel(R)Xeon(R)CPU5150@2.66GHzprocessorvendor_idcpufamilyimodelimodelnamei.…從上面的信息可以獲知,對(duì)于Xeon5150,OProfile(0.9.3)不支持性能計(jì)數(shù)器模式。接下來的所有采樣與分析都是基于timer中斷的模式。1.6.1ctpl的性能分析初始化OProfile#初始化以及啟動(dòng)oprofiledIopcontrol--resetopcontrol--setup--no-vmlinuxopcontrol--start-daemon此處,不考慮內(nèi)核及內(nèi)核模塊的Profile,只啟動(dòng)oprofiled守護(hù)進(jìn)程,而不開始profile。啟動(dòng)分析目標(biāo)程序通常需要分析的程序有兩種類型:后臺(tái)服務(wù)或者普通的應(yīng)用程序。對(duì)于已經(jīng)啟動(dòng)的后臺(tái)服務(wù),可以再其運(yùn)行期間直接開啟oprofile進(jìn)行分析即可,對(duì)于后者,需要手動(dòng)啟動(dòng)目標(biāo)程序,可以將目標(biāo)程序啟動(dòng)在后臺(tái),也可以在另外的終端啟動(dòng),以免對(duì)oprofile的控制發(fā)生影響。此處,在后臺(tái)啟動(dòng)目標(biāo)程序test_ctpl:cd/home/gonglei/public/test/z_func/ctpl/output./test_ctpl&[1]17259Ii然后開始采樣:opcontrol--start#等待一段時(shí)間,如30秒或1分鐘Iopcontrol--shutdownI查看采樣結(jié)果此時(shí),已經(jīng)獲得了采樣結(jié)果,接下來開始分析:TOC\o"1-5"\h\zII:#opreport--long-filenamesIIICPU:CPUwithtimerinterrupt,speed0MHz(estimated)iiiiProfilingthroughtimerinterrupt1ii:timer:0|samples!%|:33592972.7640/no-vmlinux11695725.3335/home/gonglei/public/test/ctpl/z_func/output/test_ctpltimer:0|samples!%|6829958.3967/home/gonglei/public/test/ctpl/z_func/output/test_ctpl4860241.5554/lib64/tls/libc-2.3.4.so560.0479/usr/lib64/libstdc++.so.6.0.386371.8708/home/yufan/querytimer:0|samples!%|496957.5316/usr/lib64/libz.so.298334.5375/lib64/tls/libc-2.3.4.so5766.6690/home/yufan/query1091.2620/lib64/tls/libpthread-2.3.4.so580.0126/usr/bin/top從上面的結(jié)果可以看到,72.76%的定時(shí)器中斷發(fā)生在內(nèi)核中,其他二進(jìn)制鏡像中,test_ctpl中發(fā)生了25.33%左右的定時(shí)器中斷,由于顯示的內(nèi)容很多,為了將注意力集中于目標(biāo),可以通過兩種辦法來過濾掉其他的profiling信息:1.使用threshold選項(xiàng):1I#opreport--long-filenames-threshold2ICPU:CPUwithtimerinterrupt,speed0MHz(estimated)Profilingthroughtimerinterrupttimer:0|iisamplesl%|33592972.7640/no-vmlinux11695725.3335/home/gonglei/public/test/ctpl/z_func/output/test_ctpltimer:0|samplesl%|i6829958.3967/home/gonglei/public/test/ctpl/z_func/output/test_ctpli4860241.5554/lib64/tls/libc-2.3.4.soi560.0479/usr/lib64/libstdc++.so.6.0.3可以看到,所有采樣百分比少于2%的鏡像都沒有再被顯示。使用鏡像名字:I#opreportimage:/home/gonglei/public/test/ctpl/z_func/output/test_ctplI|CPU:CPUwithtimerinterrupt,speed0MHz(estimated)iProfilingthroughtimerinterrupttimer:0|samplesl%|116957100.000test_ctpltimer:0|samplesl%|6829958.3967test_ctpl4860241.5554libc-2.3.4.so560.0479libstdc++.so.6.0.3此時(shí),能夠看到目標(biāo)程序test_ctpl實(shí)際占用了25.35%的執(zhí)行時(shí)間(計(jì)時(shí)器中斷比例基本可以等同為消耗時(shí)間的比例),在test_ctpl中,其自身占用的執(zhí)行時(shí)間超過一半,為58.40%,其他部分時(shí)間被c及c++的運(yùn)行時(shí)庫占用。接下來進(jìn)行更細(xì)致的函數(shù)級(jí)別的分析,通過使用opreport的-l選項(xiàng),能夠?qū)⒍M(jìn)制鏡像中所有的函數(shù)所占用的定時(shí)器中斷百分比表示出來:#opreport-limage:/home/gonglei/public/test/ctpl/z_func/output/test_ctplCPU:CPUwithtimerinterrupt,speed0MHz(estimated)Profilingthroughtimerinterrupt111isamplesi%imagenamesymbolname11115483i13.2382libc-2.3.4.sovfprintf111344211.4931test_ctplTPLBuild::BuildPage()11189537.6550libc-2.3.4.somemcpy11625515.3481test_ctplmainCallBack(void*,TPLVar*,char*,int,int)ii5607i4.7941libc-2.3.4.so_IO_default_xsputnii50624.3281test_ctplCtplBPrintf_ex(_ctpl_buf_t*,charconst*,int)39663.3910test_ctpl—gnu_cxx::__normal_iterator<TPLPage**,istd::vector<TPLPage*,std::allocator<TPLPage*>>>::—normal_iterator(TPLPage**TOC\o"1-5"\h\ziconst&)iiii38273.2721libc-2.3.4.sostrleniii36093.0857test_ctpl—gnu_cxx::__normal_iterator<TPLPage**,:std::vector<TPLPage*,std::allocator<TPLPage*>>>::base()consti35303.0182test_ctpl—gnu_cxx::__normal_iterator<TPLPage**,iii1std::vector<TPLPage*,std::allocator<TPLPage*>>>::operator*()consti34482.9481test_ctplbool—gnu_cxx::operator!=<TPLPage**,:std::vector<TPLPage*,iiistd::allocator<TPLPage*>>>(—gnu_cxx::__normal_iterator<TPLPage**,|iiistd::vector<TPLPage*,std::allocator<TPLPage*>>>const&,i__gnu_cxx::__normal_iterator<TPLPage**,std::vector<TPLPage*,std::allocator<TPLPage*>>>const&)iiI0OO——————————————————————————————————————————————————————此時(shí)出現(xiàn)的結(jié)果是按照采樣數(shù)從多到少排列的,查看結(jié)果,發(fā)現(xiàn)占用運(yùn)行時(shí)間最多的幾個(gè)Hotspot:1.13.24%libc-2.3.4.sovfprintf2.11.49%test_ctplTPLBuild::BuildPage()3.7.65%libc-2.3.4.somemcpy4.5.34%test_ctplmainCallBack(void*,TPLVar*,char*,int,int)很容易知道,在鏡像test_ctpl中,大部分時(shí)間被vfprintf、memcpy等函數(shù)消耗,這也是運(yùn)行時(shí)庫函數(shù)占用了整個(gè)鏡像40%多的執(zhí)行時(shí)間的直接原因所在。暫不考慮運(yùn)行時(shí)庫的時(shí)間消耗,只關(guān)注test_ctpl本身,使用sort選項(xiàng)對(duì)結(jié)果進(jìn)行排序:#opreport-limage:/home/gonglei/public/test/ctpl/z_func/output/test_ctpl-simageiCPU:CPUwithtimerinterrupt,speed0MHz(estimated)Profilingthroughtimerinterruptiisamplesi%imagenamesymbolname:samples%imagenamesymbolname1548313.2382libc-2.3.4.sovfprintf89537.6550libc-2.3.4.somemcpy56074.7941libc-2.3.4.so_IO_default_xsputnii827i3.2721libc-2.3.4.soi2816i2.4077libc-2.

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論