AIX進程內存分配與回收策略及應用開發建議_第1頁
AIX進程內存分配與回收策略及應用開發建議_第2頁
AIX進程內存分配與回收策略及應用開發建議_第3頁
AIX進程內存分配與回收策略及應用開發建議_第4頁
AIX進程內存分配與回收策略及應用開發建議_第5頁
已閱讀5頁,還剩33頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、 AIX 進程內存分配與回收策略及應用開發建議 目錄1. AIX 內存分配回收策略1.1 內存分配觀察示例遞增分配1.2 內存分配觀察示例遞減分配1.3 針對長運行程序的空閑內存回收1.4 mallopt 示例 11.5 mallopt 示例 21.6 內存回收 disclaim 策略1.7 disclaim/disclaim64 代碼示例1.8 內存碎片對內存回收的影響1.9 通用建議2. 內存監控2.1 觀察系統中內存占用最高的進程2.2 尋找內存持續增長的進程2.3 如何通過共享內存 ID 對應關聯到該共享內存的進程2.4 如何獲取 AIX Kernel 的內存使用率2.5 如何判斷系統

2、是否存在內存不足3. 應用開發工具3.1 dbx 使用以及 coredump 定位3.2 內存非法使用檢查3.3 內存泄漏檢查(report_allocations)3.4 內存泄漏檢查示例3.5 proctools 介紹3.6 probevue 介紹3.7 如何將 C 文件與匯編文件對應1.AIX 內存分配回收策略一般而言, 系統會直接在進程空間的free列表中維護其free釋放的內存, 以供后續新的分配直接使用,這樣可以提高分配效率,不需要每次內存分配都經過系統內核。進程退出后,系統會回收該進程占用的全部內存。注:選擇不同的分配策略時,對空閑內存空間的管理策略會有所差異。例如默認的管理結構

3、是cartesian樹;而采用watson分配算法時,使用的管理結構是紅黑樹。Cartesian笛卡爾樹參考結構:1.1 內存分配觀察示例遞增分配進程的詳細內存分配情況可以使用svmon來觀察,參考如下示例。需要注意,為方便svmon觀察,示例代碼需要在malloc之后調用memset進行初始化;因為操作系統實際上并不會立即對已申請但尚未訪問到的內容分配實際存儲空間, 而是推遲到第一次訪問時才會實際分配-這即是缺頁機制的工作原理。如下是一個申請空間遞增的應用,分配/釋放大小為2MB-4MB-8MB-16MB, 則通過各階段的svmon可以看到, 內存頁面會持續增長, 從2MB一直增加到16MB

4、 (注意 不是2MB+4MB+.+16MB=30MB) 。Malloc分配2MB,未初始化時:Address Range為0512頁,即代表5124096=2MB虛擬地址空間。Virtual取值為2,表示該空間尚未實際分配。初始化后:Virtual取值為513,表明虛存空間已經實際分配。釋放之前申請的2MB,重新 申請 4MB 并初始化后:10244096=4MB,此前釋放的512頁虛擬地址空間被重復利用。釋放之前申請的4MB,重新 申請8 8 MB 并初始化后:此前釋放的1024頁虛擬地址空間被重復利用。釋放之前申請的8MB,重新 申請 16 MB 并初始化后:1.2 內存分配觀察示例遞減分

5、配如示例, 如果是一個申請空間遞減的應用, 分配/釋放大小為16MB-8MB-4MB-2MB, 通過各階段的svmon(svmon -nrP )可以看到,內存頁面始終維持在16MB。Malloc分配16MB,未初始化時:Address Range為04096頁,即代表40964096=16MB虛擬地址空間。Inuse/Virtual取值為2,表示該空間尚未實際分配。初始化后:Virtual=4097頁, 虛擬內存已經實際分配。釋放之前申請的16MB,重新 申請8 8 MB 并初始化后:釋放之前申請的8MB,重新 申請4 4 MB 并初始化后:釋放之前申請的4MB,重新 申請2 2 MB 并初始

6、化后:可以看到svmon輸出結果沒有變化;原因是雖然應用調用了free釋放了16MB內存,但系統的處理策略是將該內存置于進程自身的空間塊樹中管理。下一個8MB分配,實際上是直接從進程已有的16MB空閑塊中獲取的。但對系統而言,進程管理的空閑塊樹也對應為該進程的內存消耗,所以其內存占用沒有變化。測試代碼:1.3 針對長運行程序的空閑內存回收由于上面介紹的內存使用方式,一個常見的現象是,對于長運行進程,其占用的私有內存大小等同于最高峰時間的內存大小。這個現象一般而言,對系統正常運行及性能的影響很小。因為如果系統空閑內存足夠,這個問題不存在。而如果內存不足,由于進程本身的空閑塊列表沒有被引用,根據換

7、頁算法,在系統缺頁(即可用內存不足)時,很容易被換出。但如果應用進程希望對其空間內存塊進行更自主的管理,可以使用mallopt接口。例如,對長運行的程序,定期在其閑時(例如每周日凌晨業務量極低時),調用 mallopt(M_DISCLAIM, 0)釋放進程私有空間的free列表。這樣可以避免在程序本身沒有內存泄漏的情況下,因業務高峰期大量的內存申請造成的進程私有free list增長,而使得進程內存占用過大。實現起來也相當簡單(參考如下 mallopt 示例)。參考mallopt函數的幫助信息:1.4 mallopt 示例 11.5 mallopt 示例 21.6 內存回收 disclaim

8、策略如果需要設置使得系統在應用調用 free 之后,即回收其內存,可以在程序啟動前設置環境變量(這兩種方式都可能對程序性能有很大影響):PSALLOC=early或者MALLOCOPTIONS=disclaim由于PSALLOC=early實際上意味著設置MALLOCOPTIONS=disclaim,且提前分配Paging Space;所以其性能開銷還要高于MALLOCOPTIONS=disclaim。但這種機制能夠避免Paging Space耗盡時,進程被系統kill掉的可能;詳情可以通過在如下aix infocenter網站查詢PSALLOC獲取。注:老的MALLOCTYPE=3.1也有此

9、效果,但該分配策略往往性能一般,且只適用于32位程序,現在的系統一般不使用了。在設置環境變量MALLOCTYPE=watson的情況下,mallopt(M_DISCLAIM,0)無效;mallopt(M_DISCLAIM,0)只對系統默認的分配策略(即cartesian樹分配算法)有效。也可以在代碼中直接用disclaim調用。注意 disclaim 調用需要在 free /delete 之前;超過 4G 的內存塊需要使用 disclaim64 函數。1.7 disclaim/disclaim64 代碼示例1.8 內存碎片對內存回收的影響需要注意的是,上面各種釋放進程私有空閑內存列表的方法,在

10、應用出現嚴重內存碎片的情況下,都存在不足。這種情況需要實際應用程序通過合理設計,避免嚴重內存碎片。例如一些緩存數據庫表的數據結構,可能涉及大量記錄的增刪,且一般不會一次性全部刪除,類似這種情況可能最終造成嚴重內存碎片;從而使得進程私有空間無法有效回收, 只能存在于進程自身的私有free list中。舉一個極端的例子,一個進程申請了4000頁內存,但釋放時,恰好在每個內存頁上保留了一個16字節的數據結構(其他空間均釋放)。這樣進程的私有內存空間實際上無法進行收縮。因為mallopt(M_DISCLAIM, 0)和disclaim等方法都需要以多個頁面為單位進行實際回收。但如果應用設計良好,一般可

11、以避免這類問題:例如一些事務性的應用,在事務處理開始時,大量申請內存;在處理結束后, 就將這些內存釋放。這種情況下, 出現大量內存碎片的概率較低。1.9 通用建議一般對內存受限程序的建議是:a. 盡量使用malloc而不是callocb. 提高引用局部性,即僅在數據結構馬上要被使用前,對其進行初始化。c. 對大的數據結構,如果使用一次后,后續不再使用,建議調用disclaim回收其分配的內存。參考:/infocenter/aix/v6r1/index.jsp性能管理和調整 性能管理 性能規劃和實現 有效的程序設計和實現 內存限制程序:要將數據工作集減至最小,請嘗試集中常用數據以及避免對虛擬存儲

12、器頁面不必要的引用。特別是:i. 用 malloc() 或 calloc() 子例程來僅請求實際需要的空間大小。當實際情況只使用數組的一小部分時,切勿請求然后初始化最大的數組。當您得到一個新頁面用來初始化數組元素時,您實際上是強制 VMM 從別處竊取一個實內存頁面。隨后, 當擁有該頁面的進程嘗試再次訪問它時,會造成缺頁故障。malloc() 和 calloc() 子例程的差異不僅僅在接口上。ii. 因為 calloc() 子例程將分配的存儲器置零, 它與每一個分配的頁面相關, 而 malloc() 子例程只與第一個頁面相關。如果您用 calloc() 子例程分配一大塊區域, 然后最初只使用一小

13、部分,那么您對系統施加了不必要的負載。不僅這些頁面必須初始化;而且如果它們的實內存頁面被系統回收(因為系統調頁), 那么已初始化但從未使用的頁面必須寫出到調頁空間。這種情況浪費 I/O 和調頁空間。iii. 大結構(如緩沖區)的鏈表可以引起類似的問題。如果您的程序執行大量尋找某個特定關鍵字的鏈式跟蹤,請考慮保持鏈接指針和關鍵字與數據分離或使用散列表方法來代替。iv. 引用局部性也意味著時間上的局部性, 而不僅僅是地址空間上。僅在使用之前初始化數據結構(如果使用的話)。在重負載系統中,在初始化和使用之間長時間駐留的數據結構有幀被竊取(因為系統調頁)的危險。然后您的程序就會在開始使用數據結構時發生

14、不必要的缺頁故障。v. 同樣,如果早先使用一個大結構,然后與程序剩余部分無關聯,它應該被釋放。使用 free()子例程來釋放由 malloc() 或 calloc() 子例程分配的空間是不夠的。free() 子例程僅僅釋放結構占用的地址范圍。要釋放實內存和調頁空間,也可使用 disclaim() 子例程來放棄空間。對disclaim() 的調用應該在調用 free() 之前進行。2. 內存監控2.1 觀察系統中內存占用最高的進程后臺運行 3 個 nmem64 進程:./nmem64 -m 2048 -s 3000 -z 80 &按進程使用的虛擬內存進行排序,顯示占用最高的前三項:顯示虛擬內存占

15、用最高的 3 個進程的詳細的內存段分布信息,如下:可以看到,消耗最多虛擬內存的段都是 nmem64 進程的數據段。2.2 尋找內存持續增長的進程可以使用 ps vg 記錄當前系統中各進程的內存消耗情況,然后通過比較多次 ps vg 的結果來判斷是否存在一些進程有持續的內存增長。說明:進程存在持續內存增長并不一定意味著出現了內存泄漏。由于 AIX 內存分配采用了訪問時分配的策略, 進程申請大量內存時系統并不會第一時間分配內存, 而是在進程使用過程中實際訪問時才進行分配。由于這種分配策略, 進程在啟動初期可能存在內存持續增長的可能 (例如數據庫緩存需要一定時間才能完全填充) ;但其增長曲線應該是收

16、斂到具體值的。測試腳本如下:2.3 如何通過共享內存 ID 對應關聯到該共享內存的進程在 AIX 系統層面,只要給定共享內存 id,就可以獲取 attach 該共享內存的進程列表,方法如下:可以根據其共享段 SID,獲得相應的關聯進程 pid,如下。注意 ipcs 上看 NATTACH=53,即有 53 個進程 attach 到該共享內存,因此 svmon 結果中,進程列表部分對應列出了 53 個進程 pid。根據相應的 pid 可以獲取進程的具體信息:2.4 如何獲取 AIX Kernel 的內存使用率kernel大部分內存占用采用跟普通進程一樣的內存段方式組織, 比如kernel heap

17、(這部分內存消耗包含文件系統的元數據、內核擴展、第三方驅動等等), 網絡buffer,磁盤管理LVM buffer占用, 以及一些RAS特性的buffer占用, 例如light-weight memory trace buffers, component tracebuffers等等。這部分都可以通過svmon -Ss 查詢出( 注意這條命令阻塞時間較長)。少部分采用非段方式組織的主要是AIX內存管理的元數據如頁表之類??梢酝ㄟ^ perfpmr.sh - - x memdetails.sh 獲取kernel內存占用的整體情況,內存分布將輸出在中。也可以通過如下方法直接觀察 AIX Kernel

18、 內存使用情況:1. 觀察AIX內存使用的命令(基于kdb,建議僅在測試環境驗證)2. 建議從我們目前實驗的幾個系統看,超過100G的大分區,一般內核的內存占用實際都在 5%以下。如果客戶環境中采用了較多第三方驅動或組件,比例可能偏高一些,建議搭建環境驗證一下。此外, 如果系統中存在超大的JFS2文件系統, 包含大量的巨型文件 (比如單個文件數十、 數百GB) ,或者有數以十萬、百萬計的小文件;則可能觀察到較高的JFS2 元數據緩存占用,或者inode緩存占用。這部分內存消耗也會計入AIX kernel,可以通過 cat/proc/sys/fs/jfs2/memory_usage觀察到:# c

19、at /proc/sy s/fs/jfs2/memory_usagemetadata cache: 38928384inode cache: 307888128total: 346816512另,文件系統的元數據緩存和inode緩存可以通過如下ioo參數控制這兩個參數是比例系數,設置為400時,元數據和inode緩存最多能占據系統內存的16%左右。一般而言,如果分區內存不大或者元數據相關操作不多,使用默認值(AIX7.1為200)通常是可行的。但如果分區內存足夠大(比如100GB以上),元數據操作較多,則可以考慮將這兩個參數設置為100,可以使得元數據和inode緩存最多占用系統內存的比例下調

20、至4%左右。2.5 如何判斷系統是否存在內存不足預期的內存需求是 virtual 頁面數加上文件頁面數(包括 pers 和 clnt) ,如果這兩者之和大于實際配置的內存頁面數,即可認為存在內存不足,如下示例:AIX 6.1 TL2版本之后,加入了一個新的available列:The available means number of bytes of memory that can be used without paging working storage.available計算大致的公式是:available = free + numperm - min(numperm,minperm)

21、- minfree注:numperm即文件緩存所占內存;minperm為文件系統內存需要保障的比例(minperm%)換算得到的內存需求;minfree是系統內存池需要保持的空閑容量(vmo參數);available 如果不夠了,就會開始 paging 了, 這是目前最直接的判斷方法。3.4 應用開發工具3.1 dbx 使用以及 coredump 定位Core dump 定位參考:/developerworks/cn/aix/library/0806_chench_core/dbx 使用參考“General Programming Concepts” “調試程序”部分。下載地址:/infoce

22、nter/aix/v6r1/topic/com.ibm.aix.genprogc/doc/genprogc/genprogc_pdf.pdf3.2 內存非法使用檢查大部分的 coredump 都與內存非法使用有關。IBM Rational PurifyPlus 是解決這類問題的最佳工具。使用 Purify 插樁編譯后再進行功能測試, 如果測試中發現內存非法使用之類 (包括內存泄漏)的問題, Purify 可以提供 GUI 界面直接關聯到出現問題的應用源代碼, 這樣能夠很方便的定位內存使用類的問題。此外,Quantify 組件可以用于分析程序的性能問題。這些工具功能都非常完備。AIX 下可免費使

23、用的非法內存使用檢查工具是 Malloc Debug Tool,設置好 MALLOCTYPE 和 MALLOCDEBUG 選項后, 啟動程序即可打開 malloc 調試功能。如下是常用的一組選項:MALLOCTYPE=debugMALLOCDEBUG=log,postfree_checking,validate_ptrs,catch_overflow,allow_overread,report_allocations,continue,output:/tmp/malloclog.txt如果允許越界讀(一般情況下不會造成嚴重錯誤) ,可以在 MALLOCDEBUG 中加入allow_overre

24、ad。打開 MALLOCDEBUG 后默認的行為是發現內存使用錯誤后調用 abort 終止程序,這樣可以在第一時間 core dump 并退出,方便定位問題。但如果不希望終止可以使用 continue 參數,這樣對于可以恢復的錯誤,將僅生成 core,進程會繼續執行。或:MALLOCDEBUG=report_allocations,log:extended,stack_depth:8,catch_overflow,allow_overread,postfree_checking,validate_ptrs,continue,output:/tmp/malloclog.txt具體可以參考:/in

25、focenter/aix/v7r1/topic/com.ibm.aix.genprogc/doc/genprogc/debug_malloc.htm注意:使用 MALLOCDEBUG 選項之后,為調試之目的,系統的內存使用可能會成倍增加,所以需要事先預留好系統的可用內存。3.3 內存泄漏檢查(report_allocations)MALLOCTYPE/MALLOCDEBUG 環境變量選項也可以用于內存泄露檢查,如:MALLOCTYPE=debugMALLOCDEBUG=report_allocations,output:/tmp/malloclog.txt更詳細的記錄:MALLOCTYPE=d

26、ebugMALLOCDEBUG=report_allocations,log:extended,stack_depth:6,output:/tmp/malloclog.txt原理:report_allocations 選項可以用于幫助發現內存泄露問題, report_allocations 選項采用數據庫記錄所有分配情況:當成功分配內存時,采用數據庫記錄分配情況;而在該內存被釋放時,則從數據庫從刪除分配記錄;當進程退出時,系統將所有未釋放內存的詳細信息記錄到日志中。注意事項:1. 從上面的原理介紹可以看到, 程序必須退出之后才能確切知道那些內存沒有對應的釋放操作。因此如果是長運行的程序,必須注

27、冊一個退出函數,常見的方法是注冊一個信號處理函數,在收到 SIGTERM 或 SIGINT 時調用 exit(0) ,參考如下示例 (sig_handle 定義和注冊過程代碼已用紅色標注)。2. 上述 debug 環境變量應該設置為僅僅對目標測試程序生效,不能直接在用戶環境中export,否則將造成大量無關程序的分配信息被記錄到日志中,對定位問題造成干擾。3. 激活 Malloc log 之后,對于 32 位程序,每次內存分配大約有 50-100 字節的額外開銷;對 64 位程序,每次內存分配有 100-200 字節的額外開銷。因此,激活調試選項的應用的內存使用量會有一定的增長,在測試時需要預先準備足夠的系統內存。4. 示例如下:參考文章:/developerworks/cn/aix/library/aumallocdebug.html3.4 內存泄漏檢查示例示例 1(基本輸出) :示例 2(擴展輸出) :3.5 proctools 介紹AIX 提供了一系列基于/proc 文件系統的 proctools 工具集用于分析應用問題,例如 procstack用于打印進程當前的棧信息;procldd 顯示進程加載的共享庫信息;procfiles 顯示進程打開的文件信息;procwdx 顯示進程當前的工作目錄;procsig 顯示

溫馨提示

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

評論

0/150

提交評論