專利名稱:在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法
技術(shù)領(lǐng)域:
本發(fā)明涉及內(nèi)存分配領(lǐng)域,特別涉及在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法。
背景技術(shù):
隨著處理器技術(shù)的快速發(fā)展,處理器速度和存儲(chǔ)系統(tǒng)之間的速度差已經(jīng)越來(lái)越大。存儲(chǔ)系統(tǒng)的速度正成為計(jì)算機(jī)整體運(yùn)行速度進(jìn)一步提高的瓶頸。為了提高存儲(chǔ)系統(tǒng)的速度,現(xiàn)有技術(shù)中提出了多種方法,其中的提高數(shù)據(jù)的局部性的方法可以在不增加帶寬需求的情況下提高存儲(chǔ)系統(tǒng)的性能,因而得到了廣泛的應(yīng)用。
堆(heap)是程序內(nèi)存空間中的一塊區(qū)域,程序運(yùn)行時(shí)動(dòng)態(tài)需要的內(nèi)存是從堆中進(jìn)行分配的。例如C程序通過(guò)malloc和calloc等系統(tǒng)函數(shù)從堆中申請(qǐng)內(nèi)存,用free函數(shù)將申請(qǐng)的內(nèi)存釋放回堆中;C++程序通過(guò)new操作申請(qǐng),通過(guò)delete操作釋放;Java程序也通過(guò)new操作申請(qǐng),但是通過(guò)垃圾收集器(Garbage Collector,GC)來(lái)自動(dòng)釋放不再使用的內(nèi)存。在很多程序中,堆數(shù)據(jù)占據(jù)了總數(shù)據(jù)的很大一部分,因此對(duì)堆數(shù)據(jù)進(jìn)行數(shù)據(jù)布局,對(duì)于提高數(shù)據(jù)的局部性,進(jìn)而提高存儲(chǔ)系統(tǒng)的性能具有很重要的意義。
以參考文獻(xiàn)1“X.Huang,S.M.Blackburn,K.S.McKinley,J.E.B.Moss,Z.Wang,and P.Cheng.The garbage collection advantage,improving programlocality.In Conference on Object Oriented Programming Systems Languagesand Applications,pages 69-80,2004”為代表的很多現(xiàn)有的堆數(shù)據(jù)布局方法的實(shí)現(xiàn)依賴于垃圾收集器(Garbage Collector,GC),由于GC可以在運(yùn)行時(shí)移動(dòng)對(duì)象并更新它的相關(guān)引用,因此它可以根據(jù)需要?jiǎng)討B(tài)進(jìn)行數(shù)據(jù)布局的工作。然而很多程序在運(yùn)行時(shí)得不到GC的支持,此時(shí)由于別名的存在將不能保證更新被移動(dòng)數(shù)據(jù)的所有相關(guān)引用,所以在這種情況下移動(dòng)一個(gè)數(shù)據(jù)對(duì)象可能會(huì)引起程序錯(cuò)誤。因此,為了避免程序出錯(cuò),在分配數(shù)據(jù)時(shí)就應(yīng)當(dāng)考慮數(shù)據(jù)的局部性,并把它們從合適的位置分配。池分配(PoolAllocation)是數(shù)據(jù)分配的一種方法,池分配是把所有堆數(shù)據(jù)對(duì)象分成不同的組,分配堆數(shù)據(jù)對(duì)象時(shí)從所在組的“內(nèi)存池”(Memory Pool,一段連續(xù)的內(nèi)存空間)里分配,以提高組內(nèi)的數(shù)據(jù)對(duì)象的局部性。參考文獻(xiàn)2“C.Lattner and V.Adve.Automatic pool allocationImproving performance bycontrolling data structure layout in the heap.In Conference on ProgrammingLanguage Design and Implementation,pages 129-142,2005”所公開(kāi)的一種現(xiàn)有的池分配方法是在編譯器中使用啟發(fā)式方法識(shí)別屬于同一個(gè)數(shù)據(jù)結(jié)構(gòu)(如鏈表的所有節(jié)點(diǎn),樹(shù)的所有節(jié)點(diǎn)等)的堆數(shù)據(jù)對(duì)象,然后把它們從同一個(gè)內(nèi)存池里分配。這種方法依賴于程序源代碼和特定的編譯器。
參考文獻(xiàn)3“S.Rubin,R.Bodik,and T.M.Chilimbi.An efficient profileanalysis framework for data-layout optimizations.In Annual Symposium onPrinciples of Programming Languages,pages 140-153,2002”所公開(kāi)的另外一種事先訓(xùn)練的方法可以獲得頻繁的訪存模式等信息,為各種優(yōu)化(包括池分配)提供依據(jù)。這種方法需要一次或多次專門的運(yùn)行來(lái)進(jìn)行訓(xùn)練,而且訓(xùn)練也需要尋找有代表性的輸入集。
參考文獻(xiàn)4“Q.Zhao,R.Rabbah,andW.Wong.Dynamic memoryoptimization using pool allocation and prefetching.ACM SIGARCH ComputerArchitecture News,33(5)27-32,2005”所公開(kāi)的現(xiàn)有動(dòng)態(tài)池分配方法在運(yùn)行時(shí)把從同一個(gè)調(diào)用內(nèi)存分配函數(shù)(如malloc)的調(diào)用點(diǎn)(以下簡(jiǎn)稱調(diào)用點(diǎn))分配的對(duì)象分在同一組,從同一個(gè)內(nèi)存池中分配。這種方法沒(méi)有對(duì)運(yùn)行時(shí)環(huán)境、源代碼或訓(xùn)練的依賴,對(duì)用戶透明。但是內(nèi)存分配點(diǎn)和內(nèi)存池是一一對(duì)應(yīng)的關(guān)系,不夠靈活,不能適應(yīng)以下一些常見(jiàn)的情況。
一種情況是一些關(guān)系不緊密的堆數(shù)據(jù)對(duì)象可能會(huì)從同一個(gè)調(diào)用點(diǎn)分配。例如,程序員經(jīng)常在分配內(nèi)存時(shí)使用包裝函數(shù)來(lái)增強(qiáng)程序的健壯性。包裝函數(shù)調(diào)用系統(tǒng)的分配函數(shù),并檢查返回的指針是否是合法值,圖1給出了包裝函數(shù)的一個(gè)示例。當(dāng)使用包裝函數(shù)時(shí),它包含的調(diào)用點(diǎn)分配的堆數(shù)據(jù)對(duì)象是由包裝函數(shù)的調(diào)用者決定的,因此這些對(duì)象可能完全無(wú)關(guān),但是按照文獻(xiàn)4的方法它們會(huì)從同一個(gè)池里分配。例如在SPEC2000的175.vpr,176.gcc,253.perlbmk,300.twolf等例子中,幾乎所有的內(nèi)存分配都是通過(guò)調(diào)用兩個(gè)包裝函數(shù)(一個(gè)包裝malloc,一個(gè)包裝calloc)來(lái)實(shí)現(xiàn)的,因此這幾個(gè)例子分配的大部分內(nèi)存都集中在兩個(gè)池里。這種分配結(jié)果和使用默認(rèn)的分配函數(shù)相比并沒(méi)有太大改進(jìn),不能發(fā)揮池分配的優(yōu)勢(shì)。
另一種情況是一些關(guān)系緊密的堆數(shù)據(jù)對(duì)象可能會(huì)從不同的調(diào)用點(diǎn)分配。這種情況可能是程序員的意圖(例如程序員在程序的多個(gè)位置分配節(jié)點(diǎn)的內(nèi)存,并把節(jié)點(diǎn)插入同一個(gè)鏈表),也可能是由編譯器優(yōu)化產(chǎn)生(例如編譯器對(duì)包含內(nèi)存分配的循環(huán)進(jìn)行循環(huán)展開(kāi))。按照文獻(xiàn)4的方法,這些對(duì)象會(huì)根據(jù)調(diào)用點(diǎn)不同而分散到多個(gè)池里。但是實(shí)際上,更好的分配方案是把這些關(guān)系緊密的堆數(shù)據(jù)對(duì)象從同一個(gè)池里分配。
發(fā)明內(nèi)容
本發(fā)明的目的是克服現(xiàn)有技術(shù)不能解決關(guān)系不緊密的堆數(shù)據(jù)對(duì)象因?yàn)樵谕粋€(gè)調(diào)用點(diǎn)分配而從同一個(gè)內(nèi)存池分配的問(wèn)題以及關(guān)系緊密的堆數(shù)據(jù)對(duì)象因?yàn)樵诓煌恼{(diào)用點(diǎn)分配而從不同的內(nèi)存池分配的問(wèn)題,從而提供一種在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法。
為了實(shí)現(xiàn)上述目的,本發(fā)明提供了一種在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,包括 步驟1)、接收堆數(shù)據(jù)的內(nèi)存池分配請(qǐng)求; 步驟2)、考察調(diào)用點(diǎn)上下文,將包含在包裝函數(shù)中的所述調(diào)用點(diǎn)的地址和調(diào)用最上層包裝函數(shù)的調(diào)用點(diǎn)的地址加入變長(zhǎng)調(diào)用鏈; 步驟3)、為從所述變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象選擇內(nèi)存池; 步驟4)、從所述內(nèi)存池中為所述堆數(shù)據(jù)分配空間。
上述技術(shù)方案中,所述的步驟3)包括分析變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象,為具有緊密關(guān)系的堆數(shù)據(jù)對(duì)象分配同一個(gè)內(nèi)存池,為不具有緊密關(guān)系的堆數(shù)據(jù)對(duì)象分配不同的內(nèi)存池。
上述技術(shù)方案中,所述的步驟3)包括 步驟3-1-1)、分析從所述變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象的指針信息; 步驟3-1-2)、從該變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象A和從另一變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象B具有相同的類型,并且所述A的指針保存在所述B的某個(gè)域中,所述A和B具有緊密關(guān)系,共用一個(gè)內(nèi)存池。
上述技術(shù)方案中,所述的步驟3)包括 步驟3-2-1)、分析從所述變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象的指針信息; 步驟3-2-2)、從該變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象A的指針記錄在一組對(duì)象C的某個(gè)域里,而從另一變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象B的指針也保存在這組對(duì)象C的同一個(gè)域里,并且所述A和B的類型相同,所述A和B具有緊密關(guān)系,共用一個(gè)內(nèi)存池。
上述技術(shù)方案中,所述的步驟3)包括 步驟3-3-1)、分析從所述變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象的指針信息; 步驟3-3-2)、從該變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象不和從任何其它變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象共用一個(gè)內(nèi)存池,新建一個(gè)內(nèi)存池。
上述技術(shù)方案中,所述的步驟2)包括 步驟2-1)、用當(dāng)前的調(diào)用點(diǎn)的地址查找包裝函數(shù)表,構(gòu)造變長(zhǎng)調(diào)用鏈;所述包裝函數(shù)表記錄了已知的包裝函數(shù)的信息; 步驟2-2)、用所述變長(zhǎng)調(diào)用鏈查找映射表,在無(wú)法從所述映射表中找到與該變長(zhǎng)調(diào)用鏈所對(duì)應(yīng)的內(nèi)存池的信息時(shí),執(zhí)行下一步;所述映射表保存了變長(zhǎng)調(diào)用鏈與內(nèi)存池之間的對(duì)應(yīng)關(guān)系; 步驟2-3)、根據(jù)調(diào)用點(diǎn)的地址上下文確定變長(zhǎng)調(diào)用鏈,并更新所述的包裝函數(shù)表。
上述技術(shù)方案中,所述的步驟2-1)包括 步驟2-1-1)、初始化變長(zhǎng)調(diào)用鏈為空; 步驟2-1-2)、將當(dāng)前調(diào)用點(diǎn)的地址加入變長(zhǎng)調(diào)用鏈中; 步驟2-1-3)、如果當(dāng)前調(diào)用點(diǎn)的地址在包裝函數(shù)表中,則把上一層調(diào)用點(diǎn)變?yōu)楫?dāng)前調(diào)用點(diǎn),然后重新執(zhí)行步驟2-1-2),否則,執(zhí)行步驟2-2)。
上述技術(shù)方案中,所述的步驟2-3)包括 步驟2-3-1)、初始化這次內(nèi)存分配請(qǐng)求的變長(zhǎng)調(diào)用鏈為空; 步驟2-3-2)、將當(dāng)前調(diào)用點(diǎn)的地址加入變長(zhǎng)調(diào)用鏈中; 步驟2-3-3)、如果分配的內(nèi)存對(duì)象的指針沒(méi)有被存到全局變量或堆中某個(gè)位置,而被當(dāng)前調(diào)用點(diǎn)所在的函數(shù)返回到上一層調(diào)用點(diǎn)時(shí),把當(dāng)前調(diào)用點(diǎn)的地址寫入所述包裝函數(shù)表中,上一層調(diào)用點(diǎn)變?yōu)楫?dāng)前調(diào)用點(diǎn),然后重新執(zhí)行步驟2-3-2),否則執(zhí)行步驟3)。
上述技術(shù)方案中,所述的步驟3)還包括 將所述變長(zhǎng)調(diào)用鏈與為該變長(zhǎng)調(diào)用鏈所分配的內(nèi)存池之間的對(duì)應(yīng)關(guān)系更新到所述映射表中。
上述技術(shù)方案中,所述的步驟4)包括 步驟4-1)、池分配器統(tǒng)計(jì)所述內(nèi)存池的分配次數(shù); 步驟4-2)、當(dāng)內(nèi)存池的分配次數(shù)小于第一門限時(shí),使用系統(tǒng)內(nèi)存分配器進(jìn)行分配,否則,執(zhí)行下一步; 步驟4-3)、內(nèi)存池的分配次數(shù)已經(jīng)達(dá)到了第一門限,進(jìn)一步判斷之前分配的對(duì)象大小是否超過(guò)了第二門限,當(dāng)超過(guò)時(shí),使用系統(tǒng)內(nèi)存分配器進(jìn)行分配,當(dāng)沒(méi)有超過(guò)時(shí),從段中分配。
上述技術(shù)方案中,所述的從段中分配包括 步驟4-3-1)、當(dāng)內(nèi)存池的分配次數(shù)剛達(dá)到設(shè)定門限后,該內(nèi)存池從系統(tǒng)申請(qǐng)一塊段; 步驟4-3-2)、該內(nèi)存池需要分配對(duì)象時(shí),從段中分配; 步驟4-3-3)、如果當(dāng)前的段使用完畢,則申請(qǐng)一個(gè)新段; 步驟4-3-4)、當(dāng)一個(gè)段中的對(duì)象都被釋放后,段被系統(tǒng)回收。
本發(fā)明的優(yōu)點(diǎn)在于 本發(fā)明能夠解決關(guān)系不緊密的堆數(shù)據(jù)對(duì)象因?yàn)樵谕粋€(gè)調(diào)用點(diǎn)分配而從同一個(gè)內(nèi)存池分配的問(wèn)題以及關(guān)系緊密的堆數(shù)據(jù)對(duì)象因?yàn)樵诓煌恼{(diào)用點(diǎn)分配而從不同的內(nèi)存池分配的問(wèn)題,提高了池分配的效果。
圖1為關(guān)系緊密的堆數(shù)據(jù)的示例圖; 圖2為本發(fā)明的在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法的流程圖。
具體實(shí)施例方式 下面結(jié)合附圖和具體實(shí)施方式
對(duì)本發(fā)明的方法加以說(shuō)明。
在背景技術(shù)的描述中已經(jīng)知道,參考文獻(xiàn)4所公開(kāi)的動(dòng)態(tài)池分配方法在使用包裝函數(shù)時(shí),會(huì)遇到關(guān)系不緊密的堆數(shù)據(jù)對(duì)象因?yàn)樵谕粋€(gè)調(diào)用點(diǎn)分配而從同一個(gè)內(nèi)存池分配的問(wèn)題,以及關(guān)系緊密的堆數(shù)據(jù)對(duì)象因?yàn)樵诓煌恼{(diào)用點(diǎn)分配而從不同的內(nèi)存池分配的問(wèn)題。因此,下文將就本發(fā)明如何解決上述兩個(gè)問(wèn)題分別予以說(shuō)明。
關(guān)系不緊密的堆數(shù)據(jù)對(duì)象從同一個(gè)內(nèi)存池分配的問(wèn)題 為了便于理解,在此做舉例說(shuō)明。例如在下面表1的一段程序中,使用了一個(gè)包裝函數(shù)safe_malloc(1行-8行)。在main函數(shù)中,第100行通過(guò)調(diào)用safe_malloc為一個(gè)鏈表分配了新節(jié)點(diǎn),第200行通過(guò)調(diào)用safe_malloc為一棵樹(shù)分配新葉子。
表1 如參考文獻(xiàn)4中所提到的現(xiàn)有技術(shù)在接到內(nèi)存分配請(qǐng)求時(shí),僅僅使用內(nèi)存分配函數(shù)malloc的直接調(diào)用地址(第2行)來(lái)作為所分配對(duì)象的特征,這樣會(huì)把前面所提到的需要新分配的鏈表節(jié)點(diǎn)和樹(shù)的葉子在同一個(gè)池里分配。但是很顯然它們屬于不同的數(shù)據(jù)結(jié)構(gòu),互相之間的關(guān)系并不緊密。因此,能代表它們特征的調(diào)用點(diǎn)還應(yīng)該包括包裝函數(shù)的調(diào)用點(diǎn)(分別為第100行和第200行),從而形成由內(nèi)存分配函數(shù)malloc的直接調(diào)用地址與包裝函數(shù)的調(diào)用點(diǎn)共同組成的用于內(nèi)存分配的調(diào)用鏈。當(dāng)采用上述調(diào)用鏈時(shí),鏈表節(jié)點(diǎn)和樹(shù)的葉子就可以被正確識(shí)別到兩個(gè)池里。在上面所提到的例子中,所述調(diào)用鏈的長(zhǎng)度為2,也就是調(diào)用鏈的最后2個(gè)調(diào)用點(diǎn)(即100行和2行(鏈表節(jié)點(diǎn)),或者200行和2行(樹(shù)的葉子))用于實(shí)現(xiàn)內(nèi)存分配。有時(shí)候,程序中一個(gè)包裝函數(shù)里可能調(diào)用另一個(gè)包裝函數(shù),這時(shí)應(yīng)該使用的調(diào)用鏈的長(zhǎng)度會(huì)更長(zhǎng),這樣才能找到不在包裝函數(shù)里的有意義的調(diào)用點(diǎn)。
基于上述理由,本發(fā)明可將調(diào)用鏈的長(zhǎng)度設(shè)置為可變長(zhǎng)度,通過(guò)可變長(zhǎng)度的調(diào)用鏈來(lái)消除包裝函數(shù)的不良影響。具體的說(shuō),當(dāng)接到內(nèi)存分配請(qǐng)求時(shí),首先取得內(nèi)存分配函數(shù)的直接調(diào)用地址(上例中的2行);然后分析該地址所屬函數(shù)(safe_malloc)在內(nèi)存分配函數(shù)結(jié)束后對(duì)返回的堆數(shù)據(jù)對(duì)象的操作(3行-7行),如果該函數(shù)沒(méi)有將該對(duì)象指針存入全局變量或堆中的某個(gè)位置,而只是把該指針?lè)祷厣弦粚诱{(diào)用點(diǎn)時(shí)(7行),就認(rèn)為該函數(shù)是包裝函數(shù),變長(zhǎng)調(diào)用鏈的長(zhǎng)度需要增加,以包括該函數(shù)的調(diào)用者(例如100行或200行);重復(fù)上述函數(shù)判斷以及變長(zhǎng)調(diào)用鏈長(zhǎng)度增加的過(guò)程,直到調(diào)用者不再是包裝函數(shù)為止(這個(gè)例子中,main函數(shù)不是包裝函數(shù),因此調(diào)用鏈長(zhǎng)度增加到2之后就不再增加了)。
為了避免對(duì)一個(gè)調(diào)用點(diǎn)多次識(shí)別是否為包裝函數(shù),作為一種優(yōu)選實(shí)現(xiàn)方式,可以將已經(jīng)識(shí)別出的包裝函數(shù)保存在一個(gè)表(稱作包裝函數(shù)表)中。在構(gòu)造變長(zhǎng)調(diào)用鏈時(shí),先查找包裝函數(shù)表,如果該表中沒(méi)有所要識(shí)別的包裝函數(shù),再進(jìn)行上述的識(shí)別過(guò)程。這一優(yōu)選實(shí)現(xiàn)方式能夠降低構(gòu)造變長(zhǎng)調(diào)用鏈的開(kāi)銷。
從上面的描述可以看出,與以參考文獻(xiàn)4為代表的現(xiàn)有技術(shù)中每個(gè)調(diào)用點(diǎn)對(duì)應(yīng)一個(gè)內(nèi)存池明顯不同的是,本發(fā)明中每個(gè)變長(zhǎng)調(diào)用鏈對(duì)應(yīng)一個(gè)內(nèi)存池,這個(gè)內(nèi)存池可能是該變長(zhǎng)調(diào)用鏈所獨(dú)有的(如上面例子中的簡(jiǎn)單情況),也可以是和其它變長(zhǎng)調(diào)用鏈共享的(參考下文所描述的池合并的情況)。變長(zhǎng)調(diào)用鏈與內(nèi)存池之間的對(duì)應(yīng)關(guān)系可以保存在一個(gè)映射表中。在運(yùn)行時(shí),分配器每次得到分配請(qǐng)求時(shí),先構(gòu)造該請(qǐng)求的變長(zhǎng)調(diào)用鏈,然后再查找這個(gè)映射表,得到對(duì)應(yīng)的內(nèi)存池,再?gòu)闹羞M(jìn)行分配。在一個(gè)優(yōu)選實(shí)現(xiàn)方式中,為了省略查表操作,另一種方法是在各個(gè)變長(zhǎng)調(diào)用鏈的最上層調(diào)用點(diǎn)之前,利用插樁把它對(duì)應(yīng)的內(nèi)存池id存到一個(gè)全局變量v中。這樣,當(dāng)程序從該變長(zhǎng)調(diào)用鏈調(diào)用到動(dòng)態(tài)內(nèi)存分配函數(shù)時(shí),直接查看全局變量v就可以得到對(duì)應(yīng)的內(nèi)存池,不必再進(jìn)行查表。這種插樁只在能夠保證下一次調(diào)用一定具有該變長(zhǎng)調(diào)用鏈時(shí)才進(jìn)行。
關(guān)系緊密的堆數(shù)據(jù)對(duì)象從不同的內(nèi)存池分配的問(wèn)題 在對(duì)如何解決關(guān)系緊密的堆數(shù)據(jù)對(duì)象從不同的內(nèi)存池分配的問(wèn)題做詳細(xì)說(shuō)明前,首先對(duì)關(guān)系緊密的堆數(shù)據(jù)對(duì)象這一概念加以說(shuō)明。為了方便理解,下面結(jié)合圖1所示的例子對(duì)相關(guān)概念加以說(shuō)明。
在圖1所示的例子中,包括有一個(gè)鏈表,該鏈表有三個(gè)節(jié)點(diǎn),各個(gè)節(jié)點(diǎn)上包括有三個(gè)域(即圖中被分為三段的白色方塊)兩個(gè)指針域d1和d2,分別指向動(dòng)態(tài)分配的數(shù)據(jù)(灰色方塊和斜線方塊);一個(gè)指針域next,指向鏈表的下一節(jié)點(diǎn)。
通過(guò)對(duì)堆數(shù)據(jù)對(duì)象的分析,本發(fā)明中定義了兩種關(guān)系緊密的模式。第一種模式是如果對(duì)象A和對(duì)象B具有相同的類型,并且A的指針保存在B的某個(gè)域中,則A和B很可能屬于同一個(gè)數(shù)據(jù)結(jié)構(gòu),它們之間的關(guān)系也是緊密的。例如圖1中,鏈表的各個(gè)節(jié)點(diǎn)就滿足這一種模式。第二種模式是如果對(duì)象A的指針記錄在對(duì)象C的某個(gè)域里(A和C的類型可以不同),而對(duì)象B的指針也保存在對(duì)象C的同一個(gè)域里,并且A和B的類型是相同的,則A和B可能是同一個(gè)數(shù)據(jù)結(jié)構(gòu)中的同一個(gè)動(dòng)態(tài)分配的域,在遍歷鏈表時(shí),通常會(huì)依次訪問(wèn)它們,因此它們之間也具有緊密的關(guān)系。例如圖1中,灰色方塊代表的對(duì)象就滿足這一種模式。同樣,條紋方塊代表的對(duì)象也滿足這一種模式。但是灰色對(duì)象和條紋對(duì)象之間并沒(méi)有緊密的關(guān)系,因?yàn)樗鼈儽M管類型相同,但是灰色對(duì)象的指針保存在節(jié)點(diǎn)的d1域中,而條紋對(duì)象的指針保存在節(jié)點(diǎn)的d2域中。
在對(duì)何種堆數(shù)據(jù)對(duì)象屬于關(guān)系緊密的堆數(shù)據(jù)對(duì)象做上述定義后,在本發(fā)明中就能夠識(shí)別從不同調(diào)用點(diǎn)分配的,但相互之間具有緊密關(guān)系的兩個(gè)對(duì)象,從而將它們所屬的池合并起來(lái),使它們統(tǒng)一在一個(gè)池里。例如在圖1中,假設(shè)虛線方塊包含的節(jié)點(diǎn)是從另外一段程序中分配并插入鏈表的,由于該節(jié)點(diǎn)和其他節(jié)點(diǎn)是關(guān)系緊密的,因此,這個(gè)節(jié)點(diǎn)所屬的池會(huì)和其它節(jié)點(diǎn)所屬的池合并。同樣,該節(jié)點(diǎn)的d1、d2域所指的對(duì)象所在的池也會(huì)做類似的合并。
在內(nèi)存池里的對(duì)象一般是緊密排列的,當(dāng)訪問(wèn)它們的時(shí)候會(huì)有比較好的空間局部性。這種收益只有在這些對(duì)象很多,而且對(duì)象的大小比較小的時(shí)候才比較明顯。因此在實(shí)現(xiàn)上設(shè)置了兩個(gè)門限每個(gè)內(nèi)存池在開(kāi)始時(shí),把針對(duì)自己的分配請(qǐng)求轉(zhuǎn)發(fā)給默認(rèn)的分配器,直到這個(gè)池轉(zhuǎn)發(fā)的分配請(qǐng)求超過(guò)100個(gè)(第一門限),而且這些請(qǐng)求分配的對(duì)象大小都小于128字節(jié)(第二門限)時(shí),該內(nèi)存池才申請(qǐng)一段連續(xù)的空間(段),不再把后續(xù)的分配請(qǐng)求轉(zhuǎn)發(fā),而是從這段空間中分配。門限1和門限2的值是可以調(diào)整的參數(shù)。在實(shí)際測(cè)試中,我們發(fā)現(xiàn)上述兩個(gè)值比較合適。
以上是對(duì)本發(fā)明的方法如何解決前文所提到問(wèn)題的相關(guān)思想的說(shuō)明。下面結(jié)合圖2從總體上對(duì)本發(fā)明方法的實(shí)現(xiàn)步驟予以說(shuō)明。
步驟10)、當(dāng)接收到一個(gè)分配請(qǐng)求后,查看當(dāng)前的全局變量v,如果v中有內(nèi)存池信息,則清除v的信息,然后轉(zhuǎn)到步驟60),否則,執(zhí)行下一步; 步驟20)、用當(dāng)前調(diào)用點(diǎn)的地址查包裝函數(shù)表,構(gòu)造變長(zhǎng)調(diào)用鏈。在本步驟中,通過(guò)查找包裝函數(shù)表來(lái)構(gòu)造變長(zhǎng)調(diào)用鏈。如果當(dāng)前調(diào)用點(diǎn)所在的包裝函數(shù)在過(guò)去曾經(jīng)遇到過(guò),那么這一包裝函數(shù)就會(huì)被保存在包裝函數(shù)表中,因此可以直接查找包裝函數(shù)表來(lái)構(gòu)造變長(zhǎng)調(diào)用鏈,從而達(dá)到節(jié)省開(kāi)銷的目的。在一個(gè)實(shí)施例中,本步驟可以具體包括以下步驟 步驟21)、初始化變長(zhǎng)調(diào)用鏈為空; 步驟22)、將當(dāng)前調(diào)用點(diǎn)的地址加入變長(zhǎng)調(diào)用鏈中; 步驟23)、如果當(dāng)前調(diào)用點(diǎn)的地址在包裝函數(shù)表中,則把上一層調(diào)用點(diǎn)變?yōu)楫?dāng)前調(diào)用點(diǎn),然后重新執(zhí)行步驟22),否則,執(zhí)行步驟30); 步驟30)、用變長(zhǎng)調(diào)用鏈查映射表,如果表中有對(duì)應(yīng)的內(nèi)存池信息,則轉(zhuǎn)到步驟60),否則執(zhí)行下一步; 步驟40)、根據(jù)調(diào)用點(diǎn)的上下文確定它的變長(zhǎng)調(diào)用鏈,并更新包裝函數(shù)表。本步驟同樣要構(gòu)造變長(zhǎng)調(diào)用鏈,但與步驟20)不同的是,采用了分析上下文語(yǔ)義來(lái)識(shí)別包裝函數(shù),從而構(gòu)造變長(zhǎng)調(diào)用鏈的方法。在前面的步驟20)中,存在當(dāng)前調(diào)用地址所在的包裝函數(shù)是第一次遇到的可能,此時(shí)包裝函數(shù)還沒(méi)有被寫入到包裝函數(shù)表中,因此,所得到的變長(zhǎng)調(diào)用鏈可能是不準(zhǔn)確的。這個(gè)不準(zhǔn)確的變長(zhǎng)調(diào)用鏈會(huì)在步驟30)中查映射表的時(shí)候發(fā)現(xiàn)(映射表中沒(méi)有該變長(zhǎng)調(diào)用鏈對(duì)應(yīng)的項(xiàng))。對(duì)于這種情況就需要執(zhí)行步驟40),通過(guò)上下文的語(yǔ)義來(lái)識(shí)別包裝函數(shù),從而得到準(zhǔn)確的變長(zhǎng)調(diào)用鏈,并把發(fā)現(xiàn)的包裝函數(shù)更新到包裝函數(shù)表里。
在一個(gè)實(shí)施例中,該步驟包括 步驟41)、初始化這次內(nèi)存分配請(qǐng)求的變長(zhǎng)調(diào)用鏈為空; 步驟42)、將當(dāng)前調(diào)用點(diǎn)的地址加入變長(zhǎng)調(diào)用鏈中; 步驟43)、如果分配的內(nèi)存對(duì)象指針沒(méi)有被存到全局變量或堆中某個(gè)位置,而被當(dāng)前調(diào)用點(diǎn)返回到上一層調(diào)用點(diǎn)時(shí),把當(dāng)前調(diào)用點(diǎn)的地址寫入包裝函數(shù)表中,上一層調(diào)用點(diǎn)變?yōu)楫?dāng)前調(diào)用點(diǎn),然后重新執(zhí)行步驟42),否則執(zhí)行下一步; 步驟50)、根據(jù)生成的變長(zhǎng)調(diào)用鏈確定它使用的內(nèi)存池,并更新映射表;作為一種實(shí)現(xiàn)方式,該步驟包括 步驟51)、分析該變長(zhǎng)調(diào)用鏈分配的對(duì)象的指針信息; 步驟52)、如果該變長(zhǎng)調(diào)用鏈分配的對(duì)象A和另一變長(zhǎng)調(diào)用鏈分配的對(duì)象B具有相同的類型,并且A的指針保存在B的某個(gè)域中,則A和B共用一個(gè)內(nèi)存池,執(zhí)行步驟55); 步驟53)、如果該變長(zhǎng)調(diào)用鏈分配的對(duì)象A的指針記錄在一組對(duì)象C的某個(gè)域里(A和C的類型可以不同),而另一變長(zhǎng)調(diào)用鏈分配的對(duì)象B的指針也保存在這組對(duì)象C的同一個(gè)域里,并且A和B的類型是相同的,則A和B共用一個(gè)內(nèi)存池,執(zhí)行步驟55); 步驟54)、新建一個(gè)內(nèi)存池; 步驟55)、將該變長(zhǎng)調(diào)用鏈和內(nèi)存池的對(duì)應(yīng)關(guān)系寫入映射表中; 步驟56)、考察變長(zhǎng)調(diào)用鏈的最上層地址,如果它能確定下一次內(nèi)存分配一定具有該變長(zhǎng)調(diào)用鏈,則在此地址插樁修改全局變量v,記錄對(duì)應(yīng)的內(nèi)存池信息; 步驟60)、池分配器統(tǒng)計(jì)該內(nèi)存池的分配次數(shù),當(dāng)內(nèi)存池的分配次數(shù)小于第一門限時(shí),使用系統(tǒng)內(nèi)存分配器進(jìn)行分配;當(dāng)內(nèi)存池的分配次數(shù)已經(jīng)達(dá)到了第一門限,則進(jìn)一步判斷之前分配的對(duì)象大小是否超過(guò)了第二門限,如果超過(guò),則使用系統(tǒng)內(nèi)存分配器進(jìn)行分配,如果沒(méi)有超過(guò),則從段中分配。其中,從段中分配包括 步驟61)、當(dāng)內(nèi)存池的分配次數(shù)剛達(dá)到設(shè)定門限后,該內(nèi)存池從系統(tǒng)申請(qǐng)一塊連續(xù)的空間(段); 步驟62)、該內(nèi)存池需要分配對(duì)象時(shí),從段中分配; 步驟63)、如果當(dāng)前的段使用完畢,則申請(qǐng)一個(gè)新段; 步驟64)、當(dāng)一個(gè)段中的對(duì)象都被釋放后,段被系統(tǒng)回收。
以上是對(duì)本發(fā)明方法的實(shí)現(xiàn)步驟的詳細(xì)說(shuō)明。本領(lǐng)域技術(shù)人員應(yīng)當(dāng)了解,關(guān)系不緊密的堆數(shù)據(jù)對(duì)象從同一個(gè)內(nèi)存池分配的問(wèn)題以及關(guān)系緊密的堆數(shù)據(jù)對(duì)象從不同的內(nèi)存池分配的問(wèn)題之間具有一定的獨(dú)立性。因此,本發(fā)明的方法還可以單獨(dú)解決上述兩個(gè)問(wèn)題中任意的一個(gè)。當(dāng)本發(fā)明方法用于解決關(guān)系不緊密的堆數(shù)據(jù)對(duì)象從同一個(gè)內(nèi)存池分配的問(wèn)題時(shí),可省略步驟51)-步驟53)中的相關(guān)操作。當(dāng)本發(fā)明方法用于解決關(guān)系緊密的堆數(shù)據(jù)對(duì)象從不同的內(nèi)存池分配的問(wèn)題時(shí),可省略步驟20)和步驟40)的操作,變長(zhǎng)調(diào)用鏈直接使用長(zhǎng)度為1的調(diào)用鏈(即直接調(diào)用點(diǎn))。
最后所應(yīng)說(shuō)明的是,以上實(shí)施例僅用以說(shuō)明本發(fā)明的技術(shù)方案而非限制。盡管參照實(shí)施例對(duì)本發(fā)明進(jìn)行了詳細(xì)說(shuō)明,本領(lǐng)域的普通技術(shù)人員應(yīng)當(dāng)理解,對(duì)本發(fā)明的技術(shù)方案進(jìn)行修改或者等同替換,都不脫離本發(fā)明技術(shù)方案的精神和范圍,其均應(yīng)涵蓋在本發(fā)明的權(quán)利要求范圍當(dāng)中。
權(quán)利要求
1.一種在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,包括
步驟1)、接收堆數(shù)據(jù)的內(nèi)存池分配請(qǐng)求;
步驟2)、考察調(diào)用點(diǎn)上下文,將包含在包裝函數(shù)中的所述調(diào)用點(diǎn)的地址和調(diào)用最上層包裝函數(shù)的調(diào)用點(diǎn)的地址加入變長(zhǎng)調(diào)用鏈;
步驟3)、為從所述變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象選擇內(nèi)存池;
步驟4)、從所述內(nèi)存池中為所述堆數(shù)據(jù)分配空間。
2.根據(jù)權(quán)利要求1所述的在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,其特征在于,所述的步驟3)包括分析變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象,為具有緊密關(guān)系的堆數(shù)據(jù)對(duì)象分配同一個(gè)內(nèi)存池,為不具有緊密關(guān)系的堆數(shù)據(jù)對(duì)象分配不同的內(nèi)存池。
3.根據(jù)權(quán)利要求2所述的在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,其特征在于,所述的步驟3)包括
步驟3-1-1)、分析從所述變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象的指針信息;
步驟3-1-2)、從該變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象A和從另一變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象B具有相同的類型,并且所述A的指針保存在所述B的某個(gè)域中,所述A和B具有緊密關(guān)系,共用一個(gè)內(nèi)存池。
4.根據(jù)權(quán)利要求2所述的在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,其特征在于,所述的步驟3)包括
步驟3-2-1)、分析從所述變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象的指針信息;
步驟3-2-2)、從該變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象A的指針記錄在一組對(duì)象C的某個(gè)域里,而從另一變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象B的指針也保存在這組對(duì)象C的同一個(gè)域里,并且所述A和B的類型相同,所述A和B具有緊密關(guān)系,共用一個(gè)內(nèi)存池。
5.根據(jù)權(quán)利要求2所述的在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,其特征在于,所述的步驟3)包括
步驟3-3-1)、分析從所述變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象的指針信息;
步驟3-3-2)、從該變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象不和從任何其它變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象共用一個(gè)內(nèi)存池,新建一個(gè)內(nèi)存池。
6.根據(jù)權(quán)利要求3或4或5所述的在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,其特征在于,所述的步驟2)包括
步驟2-1)、用當(dāng)前的調(diào)用點(diǎn)的地址查找包裝函數(shù)表,構(gòu)造變長(zhǎng)調(diào)用鏈;所述包裝函數(shù)表記錄了已知的包裝函數(shù)的信息;
步驟2-2)、用所述變長(zhǎng)調(diào)用鏈查找映射表,在無(wú)法從所述映射表中找到與該變長(zhǎng)調(diào)用鏈所對(duì)應(yīng)的內(nèi)存池的信息時(shí),執(zhí)行下一步;所述映射表保存了變長(zhǎng)調(diào)用鏈與內(nèi)存池之間的對(duì)應(yīng)關(guān)系;
步驟2-3)、根據(jù)調(diào)用點(diǎn)的地址上下文確定變長(zhǎng)調(diào)用鏈,并更新所述的包裝函數(shù)表。
7.根據(jù)權(quán)利要求6所述的在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,其特征在于,所述的步驟2-1)包括
步驟2-1-1)、初始化變長(zhǎng)調(diào)用鏈為空;
步驟2-1-2)、將當(dāng)前調(diào)用點(diǎn)的地址加入變長(zhǎng)調(diào)用鏈中;
步驟2-1-3)、如果當(dāng)前調(diào)用點(diǎn)的地址在包裝函數(shù)表中,則把上一層調(diào)用點(diǎn)變?yōu)楫?dāng)前調(diào)用點(diǎn),然后重新執(zhí)行步驟2-1-2),否則,執(zhí)行步驟2-2)。
8.根據(jù)權(quán)利要求6所述的在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,其特征在于,所述的步驟2-3)包括
步驟2-3-1)、初始化這次內(nèi)存分配請(qǐng)求的變長(zhǎng)調(diào)用鏈為空;
步驟2-3-2)、將當(dāng)前調(diào)用點(diǎn)的地址加入變長(zhǎng)調(diào)用鏈中;
步驟2-3-3)、如果分配的內(nèi)存對(duì)象的指針沒(méi)有被存到全局變量或堆中某個(gè)位置,而被當(dāng)前調(diào)用點(diǎn)所在的函數(shù)返回到上一層調(diào)用點(diǎn)時(shí),把當(dāng)前調(diào)用點(diǎn)的地址寫入所述包裝函數(shù)表中,上一層調(diào)用點(diǎn)變?yōu)楫?dāng)前調(diào)用點(diǎn),然后重新執(zhí)行步驟2-3-2),否則執(zhí)行步驟3)。
9.根據(jù)權(quán)利要求6所述的在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,其特征在于,所述的步驟3)還包括
將所述變長(zhǎng)調(diào)用鏈與為該變長(zhǎng)調(diào)用鏈所分配的內(nèi)存池之間的對(duì)應(yīng)關(guān)系更新到所述映射表中。
10.根據(jù)權(quán)利要求1或2或3或4或5或6所述的在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,其特征在于,所述的步驟4)包括
步驟4-1)、池分配器統(tǒng)計(jì)所述內(nèi)存池的分配次數(shù);
步驟4-2)、當(dāng)內(nèi)存池的分配次數(shù)小于第一門限時(shí),使用系統(tǒng)內(nèi)存分配器進(jìn)行分配,否則,執(zhí)行下一步;
步驟4-3)、內(nèi)存池的分配次數(shù)已經(jīng)達(dá)到了第一門限,進(jìn)一步判斷之前分配的對(duì)象大小是否超過(guò)了第二門限,當(dāng)超過(guò)時(shí),使用系統(tǒng)內(nèi)存分配器進(jìn)行分配,當(dāng)沒(méi)有超過(guò)時(shí),從段中分配。
11.根據(jù)權(quán)利要求10所述的在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,其特征在于,所述的從段中分配包括
步驟4-3-1)、當(dāng)內(nèi)存池的分配次數(shù)剛達(dá)到設(shè)定門限后,該內(nèi)存池從系統(tǒng)申請(qǐng)一塊段;
步驟4-3-2)、該內(nèi)存池需要分配對(duì)象時(shí),從段中分配;
步驟4-3-3)、如果當(dāng)前的段使用完畢,則申請(qǐng)一個(gè)新段;
步驟4-3-4)、當(dāng)一個(gè)段中的對(duì)象都被釋放后,段被系統(tǒng)回收。
全文摘要
本發(fā)明提供一種在運(yùn)行時(shí)對(duì)堆數(shù)據(jù)進(jìn)行池分配的方法,包括接收堆數(shù)據(jù)的內(nèi)存池分配請(qǐng)求;考察調(diào)用點(diǎn)上下文,將包含在包裝函數(shù)中的所述調(diào)用點(diǎn)的地址和調(diào)用最上層包裝函數(shù)的調(diào)用點(diǎn)的地址加入變長(zhǎng)調(diào)用鏈;為從所述變長(zhǎng)調(diào)用鏈所分配的堆數(shù)據(jù)對(duì)象選擇內(nèi)存池;從所述內(nèi)存池中為所述堆數(shù)據(jù)分配空間。本發(fā)明能夠解決關(guān)系不緊密的堆數(shù)據(jù)對(duì)象因?yàn)樵谕粋€(gè)調(diào)用點(diǎn)分配而從同一個(gè)內(nèi)存池分配的問(wèn)題以及關(guān)系緊密的堆數(shù)據(jù)對(duì)象因?yàn)樵诓煌恼{(diào)用點(diǎn)分配而從不同的內(nèi)存池分配的問(wèn)題,提高了池分配的效果。
文檔編號(hào)G06F12/02GK101763308SQ20091024391
公開(kāi)日2010年6月30日 申請(qǐng)日期2009年12月25日 優(yōu)先權(quán)日2009年12月25日
發(fā)明者王振江, 武成崗 申請(qǐng)人:中國(guó)科學(xué)院計(jì)算技術(shù)研究所