一種面向非固定包長的無鎖化多鏈內存管理方法
【專利摘要】本發明針對定長內存池中內存使用率偏低、不能動態調整內存池大小及其他內存管理方案不能很好的預防突發流量造成的內存抖動的問題,提出了一種面向非固定包長的無鎖化多鏈內存管理方法。首先初始化動態可伸縮內存池,即程序初始化兩個內存池管理數組,一個為快鏈的管理數組,另一個為滿鏈和非滿鏈的管理數組;然后初始化三個數組中指向可分配內存的指針為NULL;其次向申請內存的線程或進程提供相應的內存;最后回收線程或進程使用完的內存。
【專利說明】
一種面向非固定包長的無鎖化多鏈內存管理方法
技術領域
[0001]本發明屬于內存管理領域,涉及一種面向非固定包長的無鎖化多鏈內存管理方法。
【背景技術】
[0002]現在通用的內存管理模型,一般分為兩類:一類是定長內存池;另一類是Linux常用的內存管理模型DLMal 1c、PTMal 1c等。
[0003]現實項目中,開發人員為了節省程序大量Malloc/free的時間消耗,通常采用定長內存池,即在程序初始化時,直接向操作系統申請一大塊內存,并把該內存按照程序要求的固定長度劃分為更小的內存塊,然后把這些內存塊用鏈表進行管理。這樣程序進行申請和釋放內存操作時,實際上是從該內存池的空閑鏈中申請和釋放內存塊,其時間復雜度可以達到0(1)。雖然在時間效率上有很好的表現,但是定長內存池有兩個明顯的缺陷。一個是因為初始化時已經定義好了固定長度的內存塊,所以不論用戶申請多大的內存塊,該內存池總是分配給它一個固定塊大小的內存,有時這樣的內存分配會使得內存池中內存的平均使用率偏低;另一個是,一般程序在初始化時會申請多個空閑內存鏈,每個內存鏈中掛在了相同大小的內存塊,不同內存鏈中內存塊大小不同,所有內存鏈集中用數組進行管理。由于開發人員不能預估到哪個大小的內存塊常用,哪個不常用。所以為了系統的健壯性,通常會讓每條空閑內存鏈中的空閑塊數量相同。這樣也會造成內存的浪費。
[0004]另一方面對于Linux系統常用的內存管理模型DLMalloc、PTMalloc、TCMalloc來說,由于它們是操作系統的一種內存管理方案,開發者在進行開發時,為了考慮到系統的健壯性,其相對的管理方案會設計的比較復雜,不能直接用到一些應用層設備上。并且此類模型中,當遇到突發流量內存管理模型無法滿足用戶需求時,通常會向操作系統申請內存然后再分配給用戶,而當用戶使用完成后,在交還給操作系統。下次再有突發流量時,仍然按照上述步驟操作,這樣做容易照成內存抖動惡化。
【發明內容】
[0005]本發明針對定長內存池中內存使用率偏低、不能動態調整內存池大小及其他內存管理方案不能很好的預防突發流量造成的內存抖動的問題,提出了一種面向非固定包長的無鎖化多鏈內存管理方法。
[0006]本發明通過以下技術方案解決上述技術問題。
[0007]—種面向非固定包長的無鎖化多鏈內存管理方法,首先初始化動態可伸縮內存池,即程序初始化兩個內存池管理數組,一個為快鏈的管理數組,另一個為滿鏈和非滿鏈的管理數組;然后初始化三個數組中指向可分配內存的指針為NULL;其次向申請內存的線程或進程提供相應的內存;最后回收線程或進程使用完的內存。
[0008]所述向申請內存的線程或進程提供相應的內存,具體采用下列步驟:
[0009]步驟21:當用戶申請內存時,比較用戶申請的內存是否大于4k,如果是則執行步驟29,否則執行步驟22;
[0010]步驟22:計算出用戶申請的內存相應的級數,定位到第一層中管理數組相應位置,查看該位置處未滿鏈是否為空,如果為空執行步驟25,否則執行步驟23;
[0011]步驟23:從該未滿鏈中的第一個區段的空閑鏈中拿出空閑內存塊分配給用戶使用,并把該內存塊的頭部字段標志位由空閑改為等差,并且修改區段中空閑鏈表,把該區段中的占用計數TEAM結構體中的單元占用加I ;
[0012]步驟24:查看步驟23中分配區段的空閑鏈是否為空,如果為空,則把該區段以尾插法鏈入到相應級別的滿鏈中,否者結束;
[0013]步驟25:如果未滿鏈為空,則需要擴充區段;首先申請加鎖,然后查看快鏈的管理數組中相應級數的快鏈是否為空,如果不為空則執行步驟26;如果為空,則執行步驟27;
[0014]步驟26:從該快鏈中取出一個區段放入到第一層數組中,然后枚舉單元,并把該區段進行掛接,然后解鎖,累加該區段所在鏈表頭部字段;
[0015]步驟27:計算實際分配長度,然后進行申請并判斷是否成功,如果成功,則執行步驟28,否者返回-1;
[0016]步驟28:按照對應級數相應的區段大小申請一塊內存,并把該內存劃分為小的內存塊,標注內存塊頭部字段為空閑,整理空閑鏈,最后把該區段鏈入到第一層的未滿鏈中,然后分配給用戶需要使用的內存;
[0017]步驟29:直接malloc從系統中申請,申請成功后,標記內存塊頭部字段為系統,并返回給用戶使用,否則,返回-1。
[0018]所述回收線程或進程使用完的內存,具體采用下列步驟:
[0019]步驟31:當用戶釋放其使用的內存時,首先根據需要釋放的內存找到內存塊的首地址;
[0020]步驟32:根據內存塊頭部中類型標記是否為0x02,如果不是從內存池中申請得到的,則執行步驟33,否者執行步驟38;
[0021]步驟33:根據內存塊頭部結構體中的區號計算該區段的首地址,然后修改該區段的空閑鏈和占用計數;判斷該區段的空閑鏈是否為空,若為空則執行步驟34,否者執行步驟35;
[0022]步驟34:如果該區段的空閑鏈為空,則把該區段從滿鏈中摘除并把該區段從尾部鏈入到非滿鏈中;
[0023]步驟35:如果該區段的空閑鏈非空,則歸還內存塊,并修改內存塊類型字段及區段和總結構體中變量,然后是Held減I;最后判斷區段占用計數是否為0,若為0,則執行步驟36,否則表示釋放內存完成;
[0024]步驟36:如果占用計數為0,則說明該區段所有內存塊全部未使用,這時需要把該區段從未滿鏈中摘除掉,然后執行步驟37;
[0025]步驟37:從未滿鏈摘除以后,與衰減因子進行比較,如果滿足衰減因子,則把該區段是返還給操作系統,如果不滿足衰減因子,則直接把該區段放入到快鏈管理數組相對應級別中的快鏈中;
[0026]步驟38:該內存塊的內存標簽為系統,直接把該內存塊返還給操作系統。
[0027]本發明的有益效果:
[0028]1、本發明可以根據程序申請內存情況動態調整內存池相應內存塊的數量;其次,內存池分為第一層、第二層,可以大大減少加、解鎖造成的系統資源浪費;最后,第二層中的快鏈作為操作系統和第一層之間的緩沖區,可以有效解決突發流量造成的內存抖動情況。
[0029]2、本發明中一方面提高了內存使用率,并可以動態調整內存池中不同級別內存塊對應的區塊的數量。另一方面隨著申請內存塊的大小變大時,使用DS-MP算法內存池管理內存,除了第一次消耗的時間增加的較大外,以后消耗的時間增加成本較為理想。
【附圖說明】
[0030]圖1為本發明面向非固定包長的無鎖化多鏈內存管理方法流程圖;
[0031 ]圖2為本發明DS-MP算法中分配算法流程圖;
[0032]圖3為本發明DS-MP算法中回收算法流程圖。
【具體實施方式】
[0033]下面結合具體實施例對本發明作更詳細的描述:
[0034](I)實驗環境
[0035]本實驗是在I inux 64位操作系統,2.6.32內核版本,24核CPU數,頻率為1200MHz,16G內存,gcc版本為4.4.5的服務器上進行。
[0036]本發明進行了兩個模擬實驗,第一個實驗主要對比DS-MP算法的內存池和定長內存池的內存使用率;第二個實驗主要對比Mal loc/f ree、PTMal 1c、DS-MP算法內存池中分配和回收內存的時間效率。
[0037]第一個模擬實驗,首先初始化128字節、512字節、1024字節三個固定長度的內存池,然后使用程序隨機申請不大于1024字節的內存1000次,統計每次申請內存后內存使用率,最后計算使用三個固定長度的內存池和DS-MP算法的內存池之間的內存平均使用率。在DS-MP算法中,由于第一層中數組索引為等差數列,且等差值為32字節。所以,當程序隨機申請內存時,內存最大浪費值為31字節。而在固定內存池中,對于系統隨機申請的內存,內存池一般把最靠近該內存大小并且大于等于該內存的內存塊分配給系統。比如申請129字節,則浪費383字節。
[0038]第二個模擬實驗,首先使用mal 1c、tcmal 1c、DS_MP算法三種算法去申請3個不同大小的內存塊,每次申請100塊,總共申請20輪次,然后記錄所有輪次申請和釋放內存消耗的系統時間,并進行對比。
[0039](2)實驗結果和分析
[0040]在本發明中,作者使用DS-MP算法來管理內存,使得程序在分配、釋放內存時的時間消耗減小。主要從兩個方面對比了 DS-MP算法的高效性,一方面著重對比了使用定長內存池和DS-MP算法的內存池進行內存分配時的內存使用率情況,從數據上我們可以看到使用DS-MP算法的內存池內存使用率比使用定長內存池內存使用率高20%左右。另一方面著重對比了程序程序使用Mal 1c、PTMal 1c、DS-MP算法申請相同大小的內存塊時的時間消耗。其中當我們申請的內存塊小于26字節時,PTMalloc的時間消耗最少。通過數據對比我們可以看到,當申請260字節、2600字節時,使用DS-MP算法的內存池管理內存消耗的時間遠遠小于其他兩種方法消耗的時間。而且隨著申請內存塊的大小變大時,除了第一次消耗的時間增加的較大外,以后消耗的時間增加成本較為理想。
【主權項】
1.一種面向非固定包長的無鎖化多鏈內存管理方法,其特征在于:首先初始化動態可伸縮內存池,即程序初始化兩個內存池管理數組,一個為快鏈的管理數組,另一個為滿鏈和非滿鏈的管理數組;然后初始化三個數組中指向可分配內存的指針為NULL;其次向申請內存的線程或進程提供相應的內存;最后回收線程或進程使用完的內存。2.如權利要求1所述的一種面向非固定包長的無鎖化多鏈內存管理方法,其特征在于:所述向申請內存的線程或進程提供相應的內存,具體采用下列步驟: 步驟21:當用戶申請內存時,比較用戶申請的內存是否大于4k,如果是則執行步驟29,否則執行步驟22; 步驟22:計算出用戶申請的內存相應的級數,定位到第一層中管理數組相應位置,查看該位置處未滿鏈是否為空,如果為空執行步驟25,否則執行步驟23; 步驟23:從該未滿鏈中的第一個區段的空閑鏈中拿出空閑內存塊分配給用戶使用,并把該內存塊的頭部字段標志位由空閑改為等差,并且修改區段中空閑鏈表,把該區段中的占用計數TEAM結構體中的單元占用加I ; 步驟24:查看步驟23中分配區段的空閑鏈是否為空,如果為空,則把該區段以尾插法鏈入到相應級別的滿鏈中,否者結束; 步驟25:如果未滿鏈為空,則需要擴充區段;首先申請加鎖,然后查看快鏈的管理數組中相應級數的快鏈是否為空,如果不為空則執行步驟26;如果為空,則執行步驟27; 步驟26:從該快鏈中取出一個區段放入到第一層數組中,然后枚舉單元,并把該區段進行掛接,然后解鎖,累加該區段所在鏈表頭部字段; 步驟27:計算實際分配長度,然后進行申請并判斷是否成功,如果成功,則執行步驟28,否者返回-1; 步驟28:按照對應級數相應的區段大小申請一塊內存,并把該內存劃分為小的內存塊,標注內存塊頭部字段為空閑,整理空閑鏈,最后把該區段鏈入到第一層的未滿鏈中,然后分配給用戶需要使用的內存; 步驟29:直接mal 1c從系統中申請,申請成功后,標記內存塊頭部字段為系統,并返回給用戶使用,否則,返回-1。3.如權利要求1或2所述的一種面向非固定包長的無鎖化多鏈內存管理方法,其特征在于:所述回收線程或進程使用完的內存,具體采用下列步驟: 步驟31:當用戶釋放其使用的內存時,首先根據需要釋放的內存找到內存塊的首地址; 步驟32:根據內存塊頭部中類型標記是否為0x02,如果不是從內存池中申請得到的,則執行步驟33,否者執行步驟38; 步驟33:根據內存塊頭部結構體中的區號計算該區段的首地址,然后修改該區段的空閑鏈和占用計數;判斷該區段的空閑鏈是否為空,若為空則執行步驟34,否者執行步驟35; 步驟34:如果該區段的空閑鏈為空,則把該區段從滿鏈中摘除并把該區段從尾部鏈入到非滿鏈中; 步驟35:如果該區段的空閑鏈非空,則歸還內存塊,并修改內存塊類型字段及區段和總結構體中變量,然后是Held減I;最后判斷區段占用計數是否為0,若為0,則執行步驟36,否則表示釋放內存完成; 步驟36:如果占用計數為0,則說明該區段所有內存塊全部未使用,這時需要把該區段從未滿鏈中摘除掉,然后執行步驟37; 步驟37:從未滿鏈摘除以后,與衰減因子進行比較,如果滿足衰減因子,則把該區段是返還給操作系統,如果不滿足衰減因子,則直接把該區段放入到快鏈管理數組相對應級別中的快鏈中; 步驟38:該內存塊的內存標簽為系統,直接把該內存塊返還給操作系統。
【文檔編號】G06F12/02GK106095693SQ201610377594
【公開日】2016年11月9日
【申請日】2016年5月31日
【發明人】王嘯, 賀龍濤, 玄世昌, 張慧, 楊武, 曹首峰, 苘大鵬, 周立, 于賀威, 王大偉, 李城龍, 王秀文, 衛冰潔, 李曉倩, 賀欣, 袁媛, 劉培朋, 朱佳偉, 劉陽
【申請人】國家計算機網絡與信息安全管理中心