成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何判斷內存是否泄露及何處泄露

存儲 存儲軟件
在性能問題里面,內存有沒有泄露?如果有泄露,是哪里泄露了?這兩個問題是非常難判斷和定位的。甚至有廠商對內存是否健康的評判就是:下次系統重啟之前,應用能正常運行。換句話說,有內存泄露找不出來也沒關系,定期重啟一下服務器,而且在生產環境,的確有些企業是這么干的。

內存泄露為什么不容易判斷

在性能問題里面,內存有沒有泄露?如果有泄露,是哪里泄露了?這兩個問題是非常難判斷和定位的。甚至有廠商對內存是否健康的評判就是:下次系統重啟之前,應用能正常運行。換句話說,有內存泄露找不出來也沒關系,定期重啟一下服務器,而且在生產環境,的確有些企業是這么干的。

CPU如果利用率異常,可以查哪個進程中的哪個函數占用CPU多,相應的,內存也可以查哪個進程占內存多。為什么內存問題不像CPU問題那么容易定位?

[[212798]]

內存泄露是指使用內存完成后沒有釋放,內存增長并不能分辨增長出來的內存是進程真正要用的,還是進程泄露出來的。而CPU的占用是瞬時的、確定的,不存在某個進程申請了CPU占著不用的情況。

在一個討論組里,有人提問:對一個基于Java的Web系統進行壓力測試,如果虛擬用戶數從峰值下滑的同時,內存占用率卻保持在峰值不變,是否能得出Java程序存在內存泄露的問題?

回答是否定的,原因如下:

首先,內存占用率指的是什么內存的占用率?

在不同的OS上有不同的內存管理機制,比如AIX上,我們最關注是計算內存,但如果內存利用率指的是計算內存+非計算內存的話,即使內存占用率上升也說明不了太多問題。再比如Linux上,我們最關注是active內存,如果內存利用率指的是active+buffer+cache,即使內存占用率上升也說明不了太多問題。

第二,其他進程的干擾

操作系統上運行的進程千千萬,內存不下降,可能是其他應用/系統進程對內存的使用,應具體分辨是哪個進程占據了內存。因此考察是否有內存泄露應關注的是指定進程有沒有內存增長,這樣比較容易排除干擾。不過,查看進程的Data Segment也只能查看這個進程使用的一部分內存,而這個進程使用的Shared Memory Segment則不在這個指標中,但同樣需要關注(內存是分段的(Segment),每個段都是獨立的,有各自的度量讀數)

第三,進程池的原因

假如只關注計算內存(AIX),如果服務端的應用是一個100個進程的進程池,應用剛啟動的時候沒有客戶端的連接進來,因此沒有啟動任何進程,隨著客戶連接的增多,100個進程統統啟動,并常駐內存;再假如這些進程使用的內存是分配好不變的,那么內存占用率保持在峰值不變,是很正常的表現。

CICS里面也有進程常駐內存的概念。常駐內存后,進程不會掉下去,因此沒有創建、銷毀進程的開銷。

第四,JVM內存管理的原因

如果不是Java程序,內存不下降甚至內存上升,也有上述的多種原因,何況這是Java程序,存在一個JVM內存管理機制的原因。

我們曾經遇到這樣一個案例。對某Linux服務器上的某應用進行壓力測試,在一周的測試過程中,發現內存不斷增加。盡管服務器上每天定時清理內存(如下),但總趨勢仍然是內存增長。

備注:drop_caches是清理無用的cache,對于dirty狀態的是不清理的,直到dirty的內存被寫入磁盤。但如果用sync操作把dirty的內存flush到磁盤中,后續的drop_caches將釋放更多的內存。

后續我們就發現,這是JVM內存管理機制造成的內存泄露假象。該系統在測試過程中Java full GC(全量垃圾回收)沒有被調起,老年代的內存沒法被釋放。雖然應用使用的內存并沒有超過JVM設定的heap大小,但從Linux內存監控的指標上看,active內存是不斷增加的。

為什么full GC沒有被調起呢?這個場景下,老年代內存的增長會非常緩慢,幾天內都不會達到觸發full GC的標準,以致出現內存使用量不斷增長不回收的現象。并且,這個Java應用是一個獨立的Java程序,并沒有運行在應用中間件上,因此沒有中間件幫它做合理的GC策略,而應用本身也沒有去調起full GC。

后經調整應用,主動調起full GC,內存增長問題得到解決。

第五,本應用其他邏輯的干擾

也許這個應用是個接收客戶端數據報送并進行ETL處理的程序,服務端的應用在收到客戶端的數據后,開始啟動其他進程/線程/模塊去做后續處理,后續處理需要分配內存。

繼續最初的問題,回到那個基于Java的Web系統,如果虛擬用戶數從峰值下滑到0,內存占用率卻繼續上揚,是否能得出Java程序存在內存泄露的問題?

回答仍然是否,可能的原因還是上面那幾條。

總而言之,內存泄露是非常難判斷的事,需要長時間的測試才能得到猜測性結論。

誰占用的內存多

首先找到哪個應用或哪個進程占用的內存多。

1、物理內存占用

Nmon sheet

根據經驗,nmon的top sheet- Memory by command最直觀,也最容易直接看出哪個進程消耗的內存資源多。

然后采用類似ps –ef| grep java這樣的命令查看這個進程具體是什么內容。

另外,有不少命令也可以看哪個進程占用物理內存多,但講真,經常用命令行去看,但經常看不出來什么結果。例如下圖,每個進程消耗的物理內存似乎差距不大,雖然這個例子中服務器上跑oracle這樣的系統軟件,內存都是oracle占的,但即使不跑oracle,這些進程的內存占用往往也差距不大。

Svmon

列出消耗物理內存前十的進程

svmon -Pt10 | perl -e 'while(<>){print if($.==2||$&&&!$s++);$.=0 if(/^-+$/)}'

Svmon里面的inuse指的是這個進程對物理內存的消耗,包括計算內存+非計算內存。其實非計算內存,我們一般是不做過多關注的,及時占用的多,也沒什么問題。

ps

  1. ps aux | head -1 ; ps aux | sort -rn +4 | head -10 

按照占用物理內存的百分比排序,列出前十個進程。

Nmon command

  1. nmon --> t (top processes) --> 4 (order in process size) 

2、Paging Space占用

用到Paging Space不一定說明這個進程占用內存多,很有很能是它被其他進程擠出來的。查出誰在用Paging Space,大概率是查出誰是受害者。

按照占用Paging Space的進程排序

  1. svmon -P -O sortseg=pgsp 

檢查哪個進程引起的Paging到Paging Space(IBM script)。腳本發現po這個指標大于50的時候保存進程相關信息退出

Paging Space一旦為這個分頁分配了磁盤空間,就不會因為這個分頁換回物理內存而釋放,因此經常可以看到Paging Space的利用率不為0,但此時物理內存占用也不多。Paging Space的利用率不為0只能說明歷史上有物理內存不足的情況。

進一步關注指定進程是否有泄漏

在穩定性測試(也叫持久測試或疲勞測試)中,需要觀察內存是否有泄露。然而使用內存的進程千千萬,整個服務器的內存增長似乎也不能判斷某個進程的內存有泄露。因此在穩定性測試過程中往往需要全程關注指定進程的內存消耗,比如運行3天、7天。

查看內存使用情況的命令有ps、sar、svmon、vmstat等等,但本文并不從工具使用的角度來介紹,而是從性能測試中關注指標的角度來介紹。如果采用其他命令查看內存,需注意,相似的名字在不同命令當中的含義是不一樣的,一定要搞清楚這個字段的真正含義。

例1:Virtual這個詞,有時候在內存里面指Paging Space(換頁空間),有時指進程空間里面占用的所有分頁(包括物理內存和Paging Space中的分頁)。

例2:Nmon中的PgIn/PgOut、topas中的PageIn/PageOut是指對文件系統的換頁,而vmstat中的pi/po是對Paging Space的換頁,而topas P中進程的PAGE SPACE是指進程的Data Segment。

進程使用的數據段

1. 獲取來源

ps gv 進程號:SIZE(單位為KB)

svmon –P 進程號:work process private、work shared library data、text data BSS heap、USLA heap、application stack、private load data等segment之和(單位為4KB或64KB)

topas P中進程的PAGE SPACE(單位為4KB)

2. 指標說明

內存泄露指進程自己申請分配、使用了內存但沒有在使用完畢后釋放,大量的泄露會導致物理內存用滿,降低系統效率。

如何判斷一個進程有沒有內存泄露?AIX中使用ps gv命令觀察特定進程的SIZE指標,如果SIZE經過長時間測試后,不斷增長,則可能有內存泄露的嫌疑,這里說的是嫌疑,而不是一定。況且,查看進程的SIZE值也只能查看這個進程使用的一部分內存,而這個進程使用的Shared Memory Segment則不在這個指標中。如果是JAVA程序由于涉及到JVM的內存管理,問題就更難判斷的,我們先放下JAVA程序不表,單說C的程序。

SIZE在ps命令當中的解釋是The virtual size of the data section of the process (in 1KB units)。為什么看這個指標,則需要從進程空間開始說。

進程空間的內存可以分為三種類型:

1)數據段:Data Segment (Data + BSS + Heap)

2)棧:Stack

3)代碼段:Code Segment

棧(Stack):包括返回地址、自動分配的變量,都是一會兒有一會兒沒的,系統自動回收,不會造成內存泄露。

代碼段:進程跑起來肯定要有代碼,代碼基本上可以說是固定大小的,不會造成內存泄露。當然如果代碼太大,裝不進內存,那就另當別論了。

剩下的數據段就是進程自己分配、使用的分頁,數據段包括Data + BSS + Heap。

Data是已經初始化的全局和靜態變量。

BSS是未初始化的全局和靜態變量,比如static int i。

Heap(堆)是進程中malloc, realloc等函數申請的,需要free等函數釋放。

3. 舉例

ps gv命令中SIZE就是該進程數據段的virtual size(1KB為單位),這些分頁可能在物理內存中也可能在Paging Space中。

檢查SIZE列在長期的測試過程中是否有明顯的持續增長,如有,說明可能有內存泄露。

長期的抓取和后期的圖形化處理,可以寫腳本或代碼來實現

其他命令也可以看到這個值,以下圖為例“svmon –P 進程號”可以看work process private的virtual大小+work shared library data的virtual大小。如果有text data BSS heap、USLA heap、application stack、private load data等segment,還需把這些segment也加上。由于svmon中統計的segment較多,因此不推薦采用svmon統計Data Segment。

二者的單位是4K的分頁。(169+85)4=2544=1016,與ps v得到的SIZE值相同。

解釋一下為什么單位是4K,svmon的輸出結果中,work process private和work shared library data的PSize(Page Size)類型是sm。而這臺機器上命令svmon顯示,只有s和m兩個類型,分別對應4KB和64KB。而sm這個類型是什么呢?

AIX上面進程空間的虛擬內存分頁默認的頁大小是4K,但POWER5+以上的處理器支持4種頁大小,分別是4KB(small),64KB(medium),16MB(large)和16GB(huge),POWER6處理器開始支持4K和64K的混合形式,即一個segment里面既有4K分頁,也有64K分頁,當需要大塊內存、需要提升性能的時候用64K分頁,當64K分頁可能會浪費內存的時候則用4K分頁。svmon命令需要告訴用戶這個segment有多少內存,為了統計時的方便,就只用一個單位來度量,這個單位就是sm中的***個字母s(small),對應的度量單位是4K,這個條記錄后面的列中的數據都依據這個度量單位出具。

另外解釋一下inuse和virtual。Svmon里面的inuse指的是這個進程對物理內存的消耗,包括計算內存+非計算內存。而virtual指的是進程空間里面的分頁,這個分頁也許在物理內存,也許在Paging Space。假如說一個進程使用的分頁都在物理內存的話,inuse>=virtual,因為此時inuse里面有文件緩存,而virtual里面沒有文件緩存,文件緩存是操作系統給緩存的,和進程空間沒關系。

也可以Topas,敲擊P,看指定進程的PAGE SPACE,也是254,254*4=1016,與ps v得到的SIZE值相同。

這里的PAGE SPACE的單位是4KB,比較好查,只要man topas就可以找到這一段:PAGE SPACE:The virtual working set size used by process (4 KB pages)

有人會問,為什么不從nmon里面取值?nmon的TOP Sheet里面的進程也有SIZE等內存的指標,但nmon的TOP Sheet中只列出占CPU比較多的N個進程,如果被監控的進程占CPU很低,就不會出現在TOP Sheet中。或者一開始被監控進程占CPU較多,后來由于它占用的CPU減少而從TOP sheet中移除了,那么我們并不知道這個進程是銷毀了還是CPU利用率太低了。

進程使用的共享內存段

除了Data Segment可以造成內存泄露,如果進程分配共享內存,也可能造成內存泄露。

共享內存是某個進程分配,其他進程可以訪問的內存段,共享內存會映射到每個進程的地址空間。

那么如何查看指定進程消耗的共享內存呢?

從進程空間的角度看,共享內存段在這里

首先,還是要介紹概念,共享內存在AIX上可能有兩種內存段:shared memory segment和memory mapped segment。為什么有兩種段呢?這是由于程序調用了不同的實現接口導致的(System V Shared Memory services (shmat) 和BSD Memory Mapped Services)。BSD Memory Mapped Services可以將文件直接映射到內存而省去中間的buffer,但它也可以用來創建共享內存,它創建出來的共享內存段就是memory mapped segment。

查看指定進程消耗的共享內存的具體方法如下:

1. 獲取來源

32位程序

svmon -P進程號| egrep "Vsid|shared memory|mmap maps"

64位程序

svmon -P進程號| egrep "Vsid|shmat/mmap"

查看virtual字段

2. 指標說明

如果查出來某個內存段是memory mapped segment類型的,這個segment里面是不是共享內存,需要用ipcs –mS輔助判斷(因為memory mapped segment也可能是文件直接映射內存)。ipcs查到的都是共享內存,因此可以通過svmon –P中這個段的Vsid( virtual segment ID)在ipcs中查找有沒有這個段號。

這里沒有現成的例子,只是截個示意圖

ipcs –mS看到的是所有共享內存段,而沒有段的大小。如果看段的大小可以加-b選項。需注意,-b選項看到的是可分配的***值,而不是已分配的。

SEGSZ的單位是Byte。-b列出共享內存段以及消息、信號量的***值,也就是可分配的***值,而不是已分配的(數據庫程序除外)。-m列出活動的共享內存段。

責任編輯:武曉燕 來源: talkwithtrend
相關推薦

2017-10-26 08:43:18

JavaScript內存處理

2021-07-26 05:16:24

HashCheck密碼隱私

2016-05-25 10:03:51

JavaScript內存泄露

2010-08-12 09:30:08

Flex內存泄露

2015-12-07 09:39:27

Java內存泄露

2013-08-07 10:07:07

Handler內存泄露

2022-10-10 11:37:14

Gomap內存

2017-05-04 16:07:11

Tomcat內存泄露

2010-11-05 13:02:58

內存iPhone

2020-06-23 09:48:09

Python開發內存

2024-11-27 13:38:30

2010-08-10 10:10:34

Flex內存泄露

2025-05-22 09:35:24

2011-06-16 10:27:55

.NET內存泄漏

2013-12-23 09:25:21

2010-09-25 11:32:24

Java內存泄漏

2022-08-26 07:33:49

內存JVMEntry

2014-10-15 10:01:12

2011-07-20 17:04:43

Objective-C 內存 內存泄露

2010-08-10 10:00:57

Flex內存
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美白人做受xxxx视频 | 中文字幕成人av | 亚洲91精品 | 欧美不卡网站 | 欧美激情精品久久久久久 | 一级黄色录像毛片 | 自拍偷拍亚洲一区 | 国产精品久久久久无码av | 国产在线小视频 | 日韩1区 | 欧美黄色性生活视频 | 久久久久久久久久久蜜桃 | 日韩免| 亚洲成av人片在线观看 | 日韩免费视频一区二区 | 亚洲一区二区三区 | 亚洲免费婷婷 | 亚洲视频网 | 久久精品一区二区 | 国产羞羞视频在线观看 | 欧美久| 日本免费在线观看视频 | 日韩成人免费av | 国产原创视频 | 中文字幕日韩一区 | 久久精品亚洲 | 国产视频一视频二 | 国产91在线播放精品91 | 久久精品国产免费高清 | 久久精品亚洲 | 亚洲超碰在线观看 | 午夜天堂精品久久久久 | 国产精品久久久久国产a级 欧美日本韩国一区二区 | 丝袜美腿一区二区三区动态图 | 草久久免费视频 | 免费成人国产 | 成人自拍视频网站 | 欧美精品一区在线 | 第一福利社区1024 | 亚洲一区在线日韩在线深爱 | 最近最新中文字幕 |