本發(fā)明涉及在計(jì)算機(jī)性能分析工具技術(shù)領(lǐng)域,一種性能分析工具中快速定位函數(shù)性能記錄的方法及裝置。
背景技術(shù):性能分析工具通常需要以函數(shù)為單位記錄相關(guān)數(shù)據(jù),并且,在性能分析工具中,產(chǎn)生數(shù)據(jù)往往耗時(shí)不多,查找函數(shù)對(duì)應(yīng)記錄所在的位置反而是性能瓶頸?,F(xiàn)有性能分析工具中使用的查找方法,主要包括了hash(哈希)查找類和二分查找類(包括平衡查找樹等)兩類。這兩類查找方法的查找速度都難以得到保證,原因在于:hash查找需要對(duì)hash算法自身的參數(shù)進(jìn)行調(diào)優(yōu)才能有較好的性能,但是性能分析工具無法為每一個(gè)被測程序做單獨(dú)優(yōu)化;而二分查找在面對(duì)大規(guī)模數(shù)據(jù)的時(shí)候,受制于cache(緩存)的大小,內(nèi)存訪問次數(shù)快速上升,性能下降非常明顯。
技術(shù)實(shí)現(xiàn)要素:本發(fā)明解決的技術(shù)問題是提供一種性能分析工具中快速定位函數(shù)性能記錄的方法及裝置,為性能分析工具中提供一種快速定位函數(shù)性能記錄內(nèi)存的方法,使其在面對(duì)大規(guī)模數(shù)據(jù)和高頻率性能采樣時(shí),仍能保持優(yōu)秀的性能。為解決上述技術(shù)問題,本發(fā)明提供了一種性能分析工具中快速定位函數(shù)性能記錄的方法,在被測程序的生成階段,為所述被測程序中的每一個(gè)被測函數(shù)進(jìn)行編號(hào),統(tǒng)計(jì)被測函數(shù)的總個(gè)數(shù),并根據(jù)統(tǒng)計(jì)的所述被測函數(shù)的總個(gè)數(shù)創(chuàng)建局部性能 記錄數(shù)組;在所述被測程序的運(yùn)行階段,根據(jù)所述被測函數(shù)的編號(hào)從所述局部性能記錄數(shù)組中查找所述被測函數(shù)對(duì)應(yīng)的性能記錄。進(jìn)一步地,所述局部性能記錄數(shù)組中存放每個(gè)被測函數(shù)對(duì)應(yīng)的性能記錄單元,或者每個(gè)被測函數(shù)對(duì)應(yīng)的性能記錄單元的指針。進(jìn)一步地,在所述被測程序的生成階段,編譯器生成表達(dá)被測函數(shù)編號(hào)的代碼;鏈接器在重定位時(shí)修改編譯器生成的代碼,為每個(gè)所述被測函數(shù)生成函數(shù)編號(hào)。進(jìn)一步地,在所述被測程序的生成階段,所述編譯器為被測函數(shù)掛接性能測量鉤子函數(shù),并將被測函數(shù)的編號(hào)作為性能測量鉤子函數(shù)的傳入?yún)?shù);在所述被測程序的運(yùn)行階段,所述被測函數(shù)運(yùn)行時(shí)進(jìn)入所述性能測量鉤子函數(shù),所述性能測量鉤子函數(shù)從傳入?yún)?shù)中獲得所述被測函數(shù)的編號(hào),并將所述被測函數(shù)的編號(hào)作為數(shù)組下標(biāo),在局部性能記錄數(shù)組中查找到對(duì)應(yīng)的性能記錄。進(jìn)一步地,所述鏈接器完成鏈接后,將所述性能測量鉤子函數(shù)、與性能分析工具的初始化函數(shù)作為一個(gè)單獨(dú)的目標(biāo)文件,分別鏈接進(jìn)入所述被測程序以及被測動(dòng)態(tài)庫;所述被測程序啟動(dòng)或者所述被測動(dòng)態(tài)庫被裝載時(shí),所述被測程序或者所述被測動(dòng)態(tài)庫的初始化函數(shù)根據(jù)統(tǒng)計(jì)的所述被測函數(shù)的總個(gè)數(shù)創(chuàng)建所述局部性能記錄數(shù)組。本發(fā)明還提供了一種性能分析工具中快速定位函數(shù)性能記錄的裝置,包括性能記錄關(guān)聯(lián)模塊和性能記錄查找模塊,其中:所述性能記錄關(guān)聯(lián)模塊用于,在被測程序的生成階段,為所述被測程序中的每一個(gè)被測函數(shù)進(jìn)行編號(hào),統(tǒng)計(jì)被測函數(shù)的總個(gè)數(shù),并根據(jù)統(tǒng)計(jì)的所述被測函數(shù)的總個(gè)數(shù)創(chuàng)建局部性能記錄數(shù)組;所述性能記錄查找模塊用于,在所述被測程序的運(yùn)行階段,根據(jù)所述被測函數(shù)的編號(hào)從所述局部性能記錄數(shù)組中查找所述被測函數(shù)對(duì)應(yīng)的性能記 錄。進(jìn)一步地,所述性能記錄關(guān)聯(lián)模塊進(jìn)一步包括編譯器代碼生成單元和鏈接器函數(shù)編號(hào)生成單元,所述編譯器代碼生成單元用于,生成表達(dá)被測函數(shù)編號(hào)的代碼;所述鏈接器函數(shù)編號(hào)生成單元,在重定位時(shí)修改所述編譯器代碼生成單元生成的所述表達(dá)被測函數(shù)編號(hào)的代碼,為每個(gè)所述被測函數(shù)生成函數(shù)編號(hào)。進(jìn)一步地,所述性能記錄關(guān)聯(lián)模塊進(jìn)一步還包括編譯器鉤子函數(shù)植入單元,所述編譯器鉤子函數(shù)植入單元用于,在所述被測程序的生成階段,為被測函數(shù)掛接性能測量鉤子函數(shù),并將被測函數(shù)的編號(hào)作為性能測量鉤子函數(shù)的傳入?yún)?shù);所述性能記錄查找模塊用于,在所述被測程序的運(yùn)行階段,所述被測函數(shù)運(yùn)行時(shí)進(jìn)入所述性能測量鉤子函數(shù),所述性能測量鉤子函數(shù)從傳入?yún)?shù)中獲得所述被測函數(shù)的編號(hào),并將所述被測函數(shù)的編號(hào)作為數(shù)組下標(biāo),在局部性能記錄數(shù)組中查找到對(duì)應(yīng)的性能記錄。進(jìn)一步地,所述性能記錄關(guān)聯(lián)模塊進(jìn)一步還包括鏈接器初始化函數(shù)鏈接單元,所述鏈接器初始化函數(shù)鏈接單元用于,所述鏈接器完成鏈接后,將所述性能測量鉤子函數(shù)、與性能分析工具的初始化函數(shù)作為一個(gè)單獨(dú)的目標(biāo)文件,分別鏈接進(jìn)入所述被測程序以及被測動(dòng)態(tài)庫。進(jìn)一步地,所述性能記錄關(guān)聯(lián)模塊進(jìn)一步還包括性能記錄數(shù)組創(chuàng)建單元,所述性能記錄數(shù)組創(chuàng)建單元用于,所述被測程序啟動(dòng)或者所述被測動(dòng)態(tài)庫被裝載時(shí),所述被測程序或者所述被測動(dòng)態(tài)庫的初始化函數(shù)根據(jù)統(tǒng)計(jì)的所述被測函數(shù)的總個(gè)數(shù)創(chuàng)建所述局部性能記錄數(shù)組。與現(xiàn)有技術(shù)相比較,本發(fā)明至少具有如下優(yōu)點(diǎn):本發(fā)明為性能分析工具提供了一種時(shí)間復(fù)雜度為O(1)的查找方法,能夠 快速完成查找函數(shù)對(duì)應(yīng)的性能記錄,解決了現(xiàn)有性能分析工具中查找性能記錄耗時(shí)長,對(duì)被測程序影響大等問題。附圖說明此處所說明的附圖用來提供對(duì)本發(fā)明的進(jìn)一步理解,構(gòu)成本申請(qǐng)的一部分,本發(fā)明的示意性實(shí)施例及其說明用于解釋本發(fā)明,并不構(gòu)成對(duì)本發(fā)明的不當(dāng)限定。在附圖中:圖1是本發(fā)明實(shí)施例中程序生成階段為函數(shù)編號(hào)的過程示意圖;圖2是本發(fā)明實(shí)施例中程序運(yùn)行階段用函數(shù)編號(hào)查找對(duì)應(yīng)性能記錄的過程示意圖。具體實(shí)施方式本實(shí)施方式提供一種在性能分析工具中快速定位函數(shù)性能記錄的方法,采用如下方案:在被測程序的生成階段,為該被測程序中的每一個(gè)需要被測量的被測函數(shù)(本文中如無特殊說明,也簡稱為被測函數(shù))進(jìn)行編號(hào),統(tǒng)計(jì)被測函數(shù)的總個(gè)數(shù),并根據(jù)統(tǒng)計(jì)的被測函數(shù)的總個(gè)數(shù)創(chuàng)建局部性能記錄數(shù)組;在被測程序的運(yùn)行階段,根據(jù)被測函數(shù)的編號(hào)從局部性能記錄數(shù)組中查找該被測函數(shù)對(duì)應(yīng)的性能記錄。其中,所述的局部性能記錄數(shù)組中存放每個(gè)被測函數(shù)對(duì)應(yīng)的性能記錄單元,或者每個(gè)被測函數(shù)對(duì)應(yīng)的性能記錄單元的指針。上述方案中,是通過為每一個(gè)被測函數(shù)編號(hào)來完成快速查找。而實(shí)現(xiàn)該功能主要依賴編譯器和鏈接器。編譯器生成表達(dá)被測函數(shù)編號(hào)的代碼,鏈接器在重定位時(shí)修改編譯器生成的代碼,生成真正的被測函數(shù)編號(hào)。在運(yùn)行時(shí),根據(jù)被測程序中被測函數(shù)的總個(gè)數(shù),建立一個(gè)數(shù)組。性能測量鉤子函數(shù)從傳入?yún)?shù)獲得被測函數(shù)的編號(hào),將該被測函數(shù)編號(hào)作為數(shù)組的下標(biāo),就可以快速定位該被測函數(shù)對(duì)應(yīng)的性能記錄。其中,本文涉及以下概念:被測程序是一個(gè)統(tǒng)稱的概念,被測程序分為:靜態(tài)鏈接的被測程序和動(dòng)態(tài)鏈接的被測程序。在靜態(tài)鏈接時(shí),主程序完全等同于被測程序;在動(dòng)態(tài)鏈接時(shí),被測程序通常包括了被測主程序和被測動(dòng)態(tài)庫。進(jìn)一步地,本實(shí)施方式提供的在性能分析工具中快速定位函數(shù)性能記錄的方法,其具體實(shí)施步驟描述如下:步驟一,編譯器生成性能測量鉤子函數(shù)的傳參代碼時(shí),將一個(gè)具有特定前綴的變量func_index_stub作為性能測量鉤子函數(shù)的一個(gè)參數(shù)傳入。可以為func_index_stub生成一種特殊的重定位類型,也可以為func_index_stub這個(gè)名字加入特殊前綴,作為標(biāo)記供鏈接器使用。鏈接器建立一個(gè)func_index變量作為被測函數(shù)編號(hào)。鏈接器在進(jìn)行重定位時(shí),可以檢查當(dāng)前正在處理的重定位項(xiàng)目的類型是否為所述的特殊重定位類型或者名字是否為所述的特定前綴的func_index_stub,如果是,則鏈接器將func_index加1,并在重定位項(xiàng)目指定的位置修改指令將func_index的值寫入。在完成最終鏈接后,func_index就是被測程序中被測函數(shù)的總數(shù)。鏈接器在重定位特殊變量func_total時(shí)將該總數(shù)寫入其中,寫入方式與前面的func_index相同。具體地,在遭遇func_total重定位項(xiàng)目時(shí),不直接寫入當(dāng)時(shí)的func_index的值,因?yàn)榇藭r(shí)鏈接可能還沒有完全完成,部分被測函數(shù)可能還沒統(tǒng)計(jì)。這時(shí),是將重定位的位置記錄下來,在整個(gè)鏈接過程完成之后,再在這個(gè)記錄的位置寫入最終的func_index值。步驟二,將性能測量鉤子函數(shù),和性能測量工具的初始化函數(shù)作為一個(gè)單獨(dú)的目標(biāo)文件,分別鏈接進(jìn)入被測程序以及每一個(gè)被測動(dòng)態(tài)庫。步驟三,被測程序啟動(dòng)或者被測動(dòng)態(tài)庫被裝載時(shí),其各自擁有的初始化函數(shù)分別根據(jù)func_total的值建立一個(gè)局部數(shù)組record_array,用于存放性能記錄。其中,數(shù)組record_array的每一個(gè)單元既可以是記錄單元,也可以是指向記錄單元的指針。步驟四,被測函數(shù)運(yùn)行時(shí),進(jìn)入性能測量鉤子函數(shù),性能測量鉤子函數(shù) 從傳參中獲得被測函數(shù)的編號(hào),然后用該編號(hào)作為數(shù)組下標(biāo),在局部record_array數(shù)組中即可安全快速的進(jìn)行性能記錄的讀寫。根據(jù)上述方案,在局部數(shù)組中,每一個(gè)編號(hào)也即每一個(gè)被測函數(shù)都有其對(duì)應(yīng)的儲(chǔ)存單元。那么,存放時(shí)根據(jù)編號(hào)找到的數(shù)組存儲(chǔ)單元,即為函數(shù)性能記錄的位置。在后續(xù)的每一個(gè)寫入和讀出時(shí),根據(jù)同一個(gè)編號(hào)在同一個(gè)局部數(shù)組中,找到的是同一個(gè)內(nèi)存位置。由于局部數(shù)組的基礎(chǔ)地址是不變的,因此,如果編號(hào)相同,也就相當(dāng)于該記錄相對(duì)數(shù)組的偏移相同,從而能夠保證最終指向的內(nèi)存區(qū)域也是相同的。為使本發(fā)明的目的、技術(shù)方案和優(yōu)點(diǎn)更加清楚明白,下文中將結(jié)合附圖對(duì)本發(fā)明的實(shí)施例進(jìn)行詳細(xì)說明。需要說明的是,在不沖突的情況下,本申請(qǐng)中的實(shí)施例及實(shí)施例中的特征可以相互任意組合。本實(shí)施例中,以x86體系插樁式性能分析工具為例,描述實(shí)現(xiàn)本發(fā)明的優(yōu)選方案。該方案在實(shí)現(xiàn)時(shí)大體分為程序生成和程序運(yùn)行兩個(gè)階段。下面依次進(jìn)行介紹。一、程序生成階段該階段有如下三個(gè)主要任務(wù):(11)為每一個(gè)被測函數(shù)掛接性能測量鉤子函數(shù),并傳入被測函數(shù)的編號(hào)作為其參數(shù);(12)統(tǒng)計(jì)被測程序中被測函數(shù)的總數(shù),并放置在指定變量中;(13)為主程序和相關(guān)動(dòng)態(tài)庫掛接特殊初始化函數(shù),用于初始化性能記錄數(shù)組。如圖1所示,該程序生成階段的具體流程描述如下:(11)編譯器掛接性能測量鉤子函數(shù),并生成代碼將被測函數(shù)編號(hào)作為性能測量鉤子函數(shù)的參數(shù)傳入結(jié)合圖1所示,被測函數(shù)為voidtest(inta,intb),出、入口性能測量鉤子分別為hook_exit(intindex)、hook_enter(intindex)。在編譯階段,編譯器在被測函數(shù)test的入口處插入hook_enter(__func_index)調(diào)用,出口處插入hook_exit(__func_index)調(diào)用。在匯編階段,匯編器為未定義的_func_index變量生成重定位項(xiàng)目。鏈接器定義一個(gè)內(nèi)存變量count來表示被測函數(shù)編號(hào), 在鏈接階段,鏈接器每處理一個(gè)hook_enter重定位項(xiàng)目,就將計(jì)數(shù)器count加1,每遇到一個(gè)__func_index重定位項(xiàng)目,就在其指定的地址處填入?yún)R編指令將count作為func_index的值傳入hook_enter或者h(yuǎn)ook_exit函數(shù)。(12)統(tǒng)計(jì)被測函數(shù)的總數(shù),并將其放入指定的特殊變量中由于鏈接器需要重定位項(xiàng)目來指導(dǎo)寫入被測函數(shù)總數(shù)的位置,具體地,可以定義一個(gè)以全局變量func_total為輸入?yún)?shù)的封裝函數(shù),封裝函數(shù)中將__func_total傳入的值作為返回值。這樣,通過調(diào)用該封裝函數(shù),可從返回值中得到被測函數(shù)的總數(shù)。鏈接器修改入?yún)___func_total的方法與任務(wù)11中的傳入___funcindex參數(shù)的做法相似,此處不再詳細(xì)贅述,其區(qū)別僅在于,由于被測函數(shù)總數(shù)在鏈接完成時(shí)才能得到,因此,鏈接器在遇到__func_total時(shí)不能立即寫入當(dāng)時(shí)的被測函數(shù)編號(hào),而是需要記錄下重定位的位置,待鏈接完成后,再在記錄位置寫下被測函數(shù)總數(shù)。(13)為主程序和相關(guān)動(dòng)態(tài)庫掛接特殊初始化函數(shù)和性能測量鉤子函數(shù)編寫初始化函數(shù)__init_fast_search,根據(jù)任務(wù)12中得出的被測函數(shù)總數(shù)創(chuàng)建性能記錄所需的內(nèi)存數(shù)組,并設(shè)置函數(shù)屬性使其會(huì)在文件被裝載時(shí)自動(dòng)執(zhí)行。具體地,在同一個(gè)源文件中添加性能測量鉤子函數(shù)hook_enter和hook_exit定義。將這三個(gè)函數(shù)編譯為一個(gè)單獨(dú)的目標(biāo)文件__fast_search.o。修改鏈接指令(可直接修改用戶的相關(guān)腳本,也可在工具鏈中做調(diào)整來完成),在最終階段將__fast_search.o鏈接到主程序和各個(gè)相關(guān)動(dòng)態(tài)庫上。二、程序運(yùn)行階段該階段主要有兩個(gè)任務(wù):(21)在初始化階段,根據(jù)被測函數(shù)總個(gè)數(shù)為性能記錄分配內(nèi)存空間;(22)在程序運(yùn)行過程中,依據(jù)被測函數(shù)的編號(hào),快速找到其對(duì)應(yīng)的性能記錄。(21)初始化性能記錄數(shù)組在被測程序或者相關(guān)被測動(dòng)態(tài)庫被裝載時(shí)___init_fast_search函數(shù)得到自動(dòng)執(zhí)行,如圖2所示。主程序和動(dòng)態(tài)庫各自鏈接了一個(gè)__fast_search.o,也就是說,主程序和動(dòng)態(tài)庫各自有一個(gè)__init_fast_search函數(shù)。每一個(gè) __init_fast_search都將根據(jù)被測函數(shù)總數(shù),創(chuàng)建自身所在動(dòng)態(tài)庫或者主程序的局部性能記錄數(shù)組。(22)依據(jù)被測函數(shù)編號(hào)查找其對(duì)應(yīng)的性能記錄如圖2,被測函數(shù)調(diào)用性能測量鉤子函數(shù)時(shí)會(huì)傳入自身編號(hào)。性能測量鉤子函數(shù)用被測函數(shù)的編號(hào)作為下標(biāo),在___init_fast_search建立的局部性能記錄數(shù)組中即可進(jìn)行對(duì)應(yīng)性能記錄的讀寫。此外,本發(fā)明實(shí)施例中還提供了一種性能分析工具中快速定位函數(shù)性能記錄的裝置,該裝置主要包括性能記錄關(guān)聯(lián)模塊和性能記錄查找模塊,其中:所述性能記錄關(guān)聯(lián)模塊用于,在被測程序的生成階段,為所述被測程序中的每一個(gè)被測函數(shù)進(jìn)行編號(hào),統(tǒng)計(jì)被測函數(shù)的總個(gè)數(shù),并根據(jù)統(tǒng)計(jì)的所述被測函數(shù)的總個(gè)數(shù)創(chuàng)建局部性能記錄數(shù)組;所述性能記錄查找模塊用于,在所述被測程序的運(yùn)行階段,根據(jù)所述被測函數(shù)的編號(hào)從所述局部性能記錄數(shù)組中查找所述被測函數(shù)對(duì)應(yīng)的性能記錄。進(jìn)一步地,所述性能記錄關(guān)聯(lián)模塊進(jìn)一步包括編譯器代碼生成單元和鏈接器函數(shù)編號(hào)生成單元,所述編譯器代碼生成單元用于,生成表達(dá)被測函數(shù)編號(hào)的代碼;所述鏈接器函數(shù)編號(hào)生成單元,在重定位時(shí)修改所述編譯器代碼生成單元生成的所述表達(dá)被測函數(shù)編號(hào)的代碼,為每個(gè)所述被測函數(shù)生成函數(shù)編號(hào)。進(jìn)一步地,所述性能記錄關(guān)聯(lián)模塊進(jìn)一步還包括編譯器鉤子函數(shù)植入單元,所述編譯器鉤子函數(shù)植入單元用于,在所述被測程序的生成階段,為被測函數(shù)掛接性能測量鉤子函數(shù),并將被測函數(shù)的編號(hào)作為性能測量鉤子函數(shù)的傳入?yún)?shù);所述性能記錄查找模塊用于,在所述被測程序的運(yùn)行階段,所述被測函 數(shù)運(yùn)行時(shí)進(jìn)入所述性能測量鉤子函數(shù),所述性能測量鉤子函數(shù)從傳入?yún)?shù)中獲得所述被測函數(shù)的編號(hào),并將所述被測函數(shù)的編號(hào)作為數(shù)組下標(biāo),在局部性能記錄數(shù)組中查找到對(duì)應(yīng)的性能記錄。進(jìn)一步地,所述性能記錄關(guān)聯(lián)模塊進(jìn)一步還包括鏈接器初始化函數(shù)鏈接單元,所述鏈接器初始化函數(shù)鏈接單元用于,所述鏈接器完成鏈接后,將所述性能測量鉤子函數(shù)、與性能分析工具的初始化函數(shù)作為一個(gè)單獨(dú)的目標(biāo)文件,分別鏈接進(jìn)入所述被測程序以及被測動(dòng)態(tài)庫。進(jìn)一步地,所述性能記錄關(guān)聯(lián)模塊進(jìn)一步還包括性能記錄數(shù)組創(chuàng)建單元,所述性能記錄數(shù)組創(chuàng)建單元用于,所述被測程序啟動(dòng)或者所述被測動(dòng)態(tài)庫被裝載時(shí),所述被測程序或者所述被測動(dòng)態(tài)庫的初始化函數(shù)根據(jù)統(tǒng)計(jì)的所述被測函數(shù)的總個(gè)數(shù)創(chuàng)建所述局部性能記錄數(shù)組。以上僅為本發(fā)明的優(yōu)選實(shí)施案例而已,并不用于限制本發(fā)明,本發(fā)明還可有其他多種實(shí)施例,在不背離本發(fā)明精神及其實(shí)質(zhì)的情況下,熟悉本領(lǐng)域的技術(shù)人員可根據(jù)本發(fā)明做出各種相應(yīng)的改變和變形,但這些相應(yīng)的改變和變形都應(yīng)屬于本發(fā)明所附的權(quán)利要求的保護(hù)范圍。顯然,本領(lǐng)域的技術(shù)人員應(yīng)該明白,上述的本發(fā)明的各模塊或各步驟可以用通用的計(jì)算裝置來實(shí)現(xiàn),它們可以集中在單個(gè)的計(jì)算裝置上,或者分布在多個(gè)計(jì)算裝置所組成的網(wǎng)絡(luò)上,可選地,它們可以用計(jì)算裝置可執(zhí)行的程序代碼來實(shí)現(xiàn),從而,可以將它們存儲(chǔ)在存儲(chǔ)裝置中由計(jì)算裝置來執(zhí)行,并且在某些情況下,可以以不同于此處的順序執(zhí)行所示出或描述的步驟,或者將它們分別制作成各個(gè)集成電路模塊,或者將它們中的多個(gè)模塊或步驟制作成單個(gè)集成電路模塊來實(shí)現(xiàn)。這樣,本發(fā)明不限制于任何特定的硬件和軟件結(jié)合。