頻繁分配釋放內(nèi)存導(dǎo)致的性能問題分析_第1頁
頻繁分配釋放內(nèi)存導(dǎo)致的性能問題分析_第2頁
頻繁分配釋放內(nèi)存導(dǎo)致的性能問題分析_第3頁
頻繁分配釋放內(nèi)存導(dǎo)致的性能問題分析_第4頁
頻繁分配釋放內(nèi)存導(dǎo)致的性能問題分析_第5頁
全文預(yù)覽已結(jié)束

下載本文檔

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

文檔簡介

內(nèi)核態(tài)與用戶態(tài)是操作系統(tǒng)的兩種運(yùn)行級別,intelcpu提供RingO-Ring3三種級別的運(yùn)行模式。RingO級別最高,Ring3最低。當(dāng)一個(gè)任務(wù)(進(jìn)程)執(zhí)行系統(tǒng)調(diào)用而陷入內(nèi)核代碼中執(zhí)行時(shí),我們就稱進(jìn)程處于內(nèi)核運(yùn)行態(tài)(或簡稱為內(nèi)核態(tài))。此時(shí)處理器處于特權(quán)級最高的(0級)內(nèi)核代碼中執(zhí)行。當(dāng)進(jìn)程處于內(nèi)核態(tài)時(shí),執(zhí)行的內(nèi)核代碼會使用當(dāng)前進(jìn)程的內(nèi)核棧。每個(gè)進(jìn)程都有自己的內(nèi)核棧。當(dāng)進(jìn)程在執(zhí)行用戶自己的代碼時(shí),則稱其處于用戶運(yùn)行態(tài)(用戶態(tài))。即此時(shí)處理器在特權(quán)級最低的(3級)用戶代碼中運(yùn)行。在內(nèi)核態(tài)下CPU可執(zhí)行任何指令,在用戶態(tài)下CPU只能執(zhí)行非特權(quán)指令。當(dāng)CPU處于內(nèi)核態(tài),可以隨意進(jìn)入用戶態(tài);而當(dāng)CPU處于用戶態(tài)時(shí),用戶從用戶態(tài)切換到內(nèi)核態(tài)只有在系統(tǒng)調(diào)用和中斷兩種情況下發(fā)生,一般程序一開始都是運(yùn)行于用戶態(tài),當(dāng)程序需要使用系統(tǒng)資源時(shí),就必須通過調(diào)用軟中斷進(jìn)入內(nèi)核態(tài)?,F(xiàn)象壓力測試過程中,發(fā)現(xiàn)被測對象性能不夠理想,具體表現(xiàn)為:進(jìn)程的系統(tǒng)態(tài)CPU消耗20,用戶態(tài)CPU消耗10,系統(tǒng)idle大約70用ps-omajflt,minflt-Cprogram命令查看,發(fā)現(xiàn)majflt每秒增量為0,而minflt每秒增量大于10000。初步分析majflt代表majorfault,中文名叫大錯(cuò)誤,minflt代表minorfault,中文名叫小錯(cuò)誤。這兩個(gè)數(shù)值表示一個(gè)進(jìn)程自啟動以來所發(fā)生的缺頁中斷的次數(shù)。當(dāng)一個(gè)進(jìn)程發(fā)生缺頁中斷的時(shí)候,進(jìn)程會陷入內(nèi)核態(tài),執(zhí)行以下操作:檢查要訪問的虛擬地址是否合法查找/分配一個(gè)物理頁填充物理頁內(nèi)容(讀取磁盤,或者直接置0,或者啥也不干)建立映射關(guān)系(虛擬地址到物理地址)重新執(zhí)行發(fā)生缺頁中斷的那條指令如果第3步,需要讀取磁盤,那么這次缺頁中斷就是majflt,否則就是minflto此進(jìn)程minflt如此之高,一秒10000多次,不得不懷疑它跟進(jìn)程內(nèi)核態(tài)cpu消耗大有很大關(guān)系。分析代碼查看代碼,發(fā)現(xiàn)是這么寫的:一個(gè)請求來,用malloc分配2M內(nèi)存,請求結(jié)束后free這塊內(nèi)存??慈罩?,發(fā)現(xiàn)分配內(nèi)存語句耗時(shí)10us,平均一條請求處理耗時(shí)1000us。原因已找到!雖然分配內(nèi)存語句的耗時(shí)在一條處理請求中耗時(shí)比重不大,但是這條語句嚴(yán)重影響了性能要解釋清楚原因,需要先了解一下內(nèi)存分配的原理。內(nèi)存分配的原理從操作系統(tǒng)角度來看,進(jìn)程分配內(nèi)存有兩種方式,分別由兩個(gè)系統(tǒng)調(diào)用完成:brk和mmap(不考慮共享內(nèi)存)。brk是將數(shù)據(jù)段(.data)的最高地址指針_edata往高地址推,mmap是在進(jìn)程的虛擬地址空間中(一般是堆和棧中間)找一塊空閑的。這兩種方式分配的都是虛擬內(nèi)存,沒有分配物理內(nèi)存。在第一次訪問已分配的虛擬地址空間的時(shí)候,發(fā)生缺頁中斷,操作系統(tǒng)負(fù)責(zé)分配物理內(nèi)存,然后建立虛擬內(nèi)存和物理內(nèi)存之間的映射關(guān)系。

在標(biāo)準(zhǔn)C庫中,提供了malloc/free函數(shù)分配釋放內(nèi)存,這兩個(gè)函數(shù)底層是由brk,mmapmunmap這些系統(tǒng)調(diào)用實(shí)現(xiàn)的。下面以一個(gè)例子來說明內(nèi)存分配的原理:1進(jìn)程啟動的時(shí)候,其(虛擬)內(nèi)存空間的初始布局如圖1所示。其中,mmap內(nèi)存映射文件是在堆和棧的中間(例如libc-2.2.93.so,其它數(shù)據(jù)文件等),為了簡單起見,省略了內(nèi)存映射文件?!猠data指針(glibc里面定義)指向數(shù)據(jù)段的最高地址。2進(jìn)程調(diào)用A=malloc(30K)以后,內(nèi)存空間如圖2:malloc函數(shù)會調(diào)用brk系統(tǒng)調(diào)用,將_edata指針往高地址推30K,就完成虛擬內(nèi)存分配。你可能會問:只要把_edata+3OK就完成內(nèi)存分配了?事實(shí)是這樣的,_edata+30K只是完成虛擬地址的分配,A這塊內(nèi)存現(xiàn)在還是沒有物理頁與之對應(yīng)的,等到進(jìn)程第一次讀寫A這塊內(nèi)存的時(shí)候,發(fā)生缺頁中斷,這個(gè)時(shí)候,內(nèi)核才分配A這塊內(nèi)存對應(yīng)的物理頁。也就是說,如果用malloc分配了A這塊內(nèi)容,然后從來不訪問它,那么,A對應(yīng)的物理頁是不會被分配的。3進(jìn)程調(diào)用B=malloc(40K)以后,內(nèi)存空間如圖3.(icxi>堆A目40KC一*14+iiWflSxfrffiTfff代同段[血mSt畑皿IM塔AJOKn-4f)Kd-ia?KC-2*0K*拽崙堆JIaKfffffrrF0=fjHoc卩陽)冊闕SO附代碼舉i.kxl)堆23QK:R/MtD-3-lfflKTX檻Steffi⑹■fr?(C)4進(jìn)程調(diào)用C=malloc(200K)以后,內(nèi)存空間如圖4:默認(rèn)情況下,malloc函數(shù)分配內(nèi)存,如果請求內(nèi)存大于128K(可由M_MMAP_THRESHOLD選項(xiàng)調(diào)節(jié)),那就不是去推_edata指針了,而是利用mmap系統(tǒng)調(diào)用,從堆和棧的中間分配一塊虛擬內(nèi)存。這樣子做主要是因?yàn)閎rk分配的內(nèi)存需要等到高地址內(nèi)存釋放以后才能釋放(例如,在B釋放之前,A是不可能釋放的),而mmap分配的內(nèi)存可以單獨(dú)釋放。當(dāng)然,還有其它的好處,也有壞處,再具體下去,有興趣的同學(xué)可以去看glibc里面malloc的代碼了。5進(jìn)程調(diào)用D=malloc(100K)以后,內(nèi)存空間如圖5.6進(jìn)程調(diào)用free(C)以后,C對應(yīng)的虛擬內(nèi)存和物理內(nèi)存一起釋放

(6:電址mnsjiLj 昭KIW闌昭日00餐碼謹(jǐn)(JCXE9蠱H段r.da(n;畝報(bào)睡3血)舷険(Ma)A-30Kh-JQKA-30K斗? ―k\)1WK11pjjk*時(shí)試葩川簡血iLSMffffffffaxffffffff0T(ffffFffF忖)(?>fre?(D)trim7進(jìn)程調(diào)用free(B)以后,如圖7所示。B對應(yīng)的虛擬內(nèi)存和物理內(nèi)存都沒有釋放,因?yàn)橹挥幸粋€(gè)_edata指針,如果往回推,那么D這塊內(nèi)存怎么辦呢?當(dāng)然,B這塊內(nèi)存,是可以重用的,如果這個(gè)時(shí)候再來一個(gè)40K的請求,那么malloc很可能就把B這塊內(nèi)存返回回去了。8進(jìn)程調(diào)用free(D)以后,如圖8所示。B和D連接起來,變成一塊140K的空閑內(nèi)存。9默認(rèn)情況下:當(dāng)最高地址空間的空閑內(nèi)存超過128K(可由M_TRIM_THRESHOLD選項(xiàng)調(diào)節(jié))時(shí),執(zhí)行內(nèi)存緊縮操作(trim)。在上一個(gè)步驟free的時(shí)候,發(fā)現(xiàn)最高地址空閑內(nèi)存超過128K,于是內(nèi)存緊縮,變成圖9所示。真相大白說完內(nèi)存分配的原理,那么被測模塊在內(nèi)核態(tài)cpu消耗高的原因就很清楚了:每次請求來都malloc一塊2M的內(nèi)存,默認(rèn)情況下,malloc調(diào)用mmap分配內(nèi)存,請求結(jié)束的時(shí)候,調(diào)用munmap釋放內(nèi)存。假設(shè)每個(gè)請求需要5個(gè)物理頁,那么每個(gè)請求就會產(chǎn)生5個(gè)缺頁中斷,在2000的壓力下,每秒就產(chǎn)生了10000多次缺頁中斷,這些缺頁中斷不需要讀取磁盤解決,所以叫做minflt;缺頁中斷在內(nèi)核態(tài)執(zhí)行,因此進(jìn)程的內(nèi)核態(tài)cpu消耗很大。缺頁中斷分散在整個(gè)請求的處理過程中,所以表現(xiàn)為分配語句耗時(shí)(10us)相對于整條請求的處理時(shí)間(1000us)比重很小。解決辦法將動態(tài)內(nèi)存改為靜態(tài)分配,或者啟動的時(shí)候,用malloc為每個(gè)線程分配,然后保存在threaddata里面。但是,由于這個(gè)模塊的特殊性,靜態(tài)分配,或者啟動時(shí)候分配都不可行。另外,Linux下默認(rèn)棧的大小限制是10M,如果在棧上分配幾M的內(nèi)存,有風(fēng)險(xiǎn)。禁止malloc調(diào)用mmap分配內(nèi)存,禁止內(nèi)存緊縮。在進(jìn)程啟動時(shí)候,加入以下兩行代碼:mallopt(M_MMAP_MAX,0);//禁止malloc調(diào)用mmap分配內(nèi)存mallopt(M_TRIM_THRESHOLD,-1);//禁止內(nèi)存緊縮效果:加入這兩行代碼以后,用ps命令觀察,壓力穩(wěn)定以后,majlt和minflt都為0。進(jìn)程的系統(tǒng)態(tài)cpu從20降到10。小結(jié)可以用命令ps-omajfltminflt-Cprogram來查看進(jìn)程的majflt,minflt的值,這兩個(gè)值都是累加值,從

溫馨提示

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

最新文檔

評論

0/150

提交評論