'怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析'

Linux Python 腳本語言 設計 路由器 Atstudy網校 2019-08-24
"

我下面這篇文章提供了一種輕巧的內存洩漏測試方法及其python實現,該方法在Lenovo Bamboo系統的驗收測試活動中得到過諸多檢驗,是一種易用有效的內存洩漏測試方法。

"

我下面這篇文章提供了一種輕巧的內存洩漏測試方法及其python實現,該方法在Lenovo Bamboo系統的驗收測試活動中得到過諸多檢驗,是一種易用有效的內存洩漏測試方法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

一、內存洩漏測試原理

1、內存洩漏的危害。

內存洩漏的危害不必多說,會導致系統的可用內存越來越少,影響系統長時間運行的穩定性。

2、常用的內存洩漏測試方法

一般而言,可概括為兩種思路:

1)內存分配、釋放工具檢查

如valgrind等內存測試工具。

2)Linux系統性能監測

如zabbix等linux性能監測工具,以及團隊自研的檢測linux性能的工具。

在方法一中,工具的原理一般是通過檢查當程序動態分配內存後,是否有釋放來判斷有沒有發生內存洩漏。其優點很明顯,發現洩漏時能很方便定位到代碼的具體哪個地方在洩漏內存。但缺點也很明顯:一是工具容易誤判,二是工具要干涉程序編譯過程,使得工具使用起來很麻煩。這兩個缺點對於黑盒測試人員來說尤其容易感受到。

其實,還有第三個缺點。作為測試人員,真正關心的難道是程序結束時內存有沒有free嗎?不然。絕大多數的進程原本就該持續運行永不結束(至少我們希望是這樣),測試人員真正關心的是進程所使用的內存是基本穩定的,還是持續增長的。如果是持續增長的,就有影響系統長時間運行穩定性的風險。

綜上, Bamboo OS測試人員根據方法二總結了內存洩漏測試方法,並利用python實現了工具腳本。

"

我下面這篇文章提供了一種輕巧的內存洩漏測試方法及其python實現,該方法在Lenovo Bamboo系統的驗收測試活動中得到過諸多檢驗,是一種易用有效的內存洩漏測試方法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

一、內存洩漏測試原理

1、內存洩漏的危害。

內存洩漏的危害不必多說,會導致系統的可用內存越來越少,影響系統長時間運行的穩定性。

2、常用的內存洩漏測試方法

一般而言,可概括為兩種思路:

1)內存分配、釋放工具檢查

如valgrind等內存測試工具。

2)Linux系統性能監測

如zabbix等linux性能監測工具,以及團隊自研的檢測linux性能的工具。

在方法一中,工具的原理一般是通過檢查當程序動態分配內存後,是否有釋放來判斷有沒有發生內存洩漏。其優點很明顯,發現洩漏時能很方便定位到代碼的具體哪個地方在洩漏內存。但缺點也很明顯:一是工具容易誤判,二是工具要干涉程序編譯過程,使得工具使用起來很麻煩。這兩個缺點對於黑盒測試人員來說尤其容易感受到。

其實,還有第三個缺點。作為測試人員,真正關心的難道是程序結束時內存有沒有free嗎?不然。絕大多數的進程原本就該持續運行永不結束(至少我們希望是這樣),測試人員真正關心的是進程所使用的內存是基本穩定的,還是持續增長的。如果是持續增長的,就有影響系統長時間運行穩定性的風險。

綜上, Bamboo OS測試人員根據方法二總結了內存洩漏測試方法,並利用python實現了工具腳本。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、linux內存管理機制

Linux的內存管理機制,網上的資料很多,就不多談了。本文只對一些基本的概念囉嗦幾句。

虛擬內存:linux上每個進程都有一個虛擬的地址空間,這個虛擬的地址空間大小在ps命令裡體現為VSZ,在top命令裡體現為VIRT。這空間可以很大,單個進程的VSZ超出整個系統的內存,也是很常見的。

常駐內存:只有實際要發生訪問的內存,才會被映射到RAM上,在ps命令裡體現為RSS,在top命令裡體現為RES

如下圖所示,vpp的VSZ為99G(你看,任性吧。),RSS為787M。

(注:PS命令中內存基本單位是KB,B代表bit)

"

我下面這篇文章提供了一種輕巧的內存洩漏測試方法及其python實現,該方法在Lenovo Bamboo系統的驗收測試活動中得到過諸多檢驗,是一種易用有效的內存洩漏測試方法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

一、內存洩漏測試原理

1、內存洩漏的危害。

內存洩漏的危害不必多說,會導致系統的可用內存越來越少,影響系統長時間運行的穩定性。

2、常用的內存洩漏測試方法

一般而言,可概括為兩種思路:

1)內存分配、釋放工具檢查

如valgrind等內存測試工具。

2)Linux系統性能監測

如zabbix等linux性能監測工具,以及團隊自研的檢測linux性能的工具。

在方法一中,工具的原理一般是通過檢查當程序動態分配內存後,是否有釋放來判斷有沒有發生內存洩漏。其優點很明顯,發現洩漏時能很方便定位到代碼的具體哪個地方在洩漏內存。但缺點也很明顯:一是工具容易誤判,二是工具要干涉程序編譯過程,使得工具使用起來很麻煩。這兩個缺點對於黑盒測試人員來說尤其容易感受到。

其實,還有第三個缺點。作為測試人員,真正關心的難道是程序結束時內存有沒有free嗎?不然。絕大多數的進程原本就該持續運行永不結束(至少我們希望是這樣),測試人員真正關心的是進程所使用的內存是基本穩定的,還是持續增長的。如果是持續增長的,就有影響系統長時間運行穩定性的風險。

綜上, Bamboo OS測試人員根據方法二總結了內存洩漏測試方法,並利用python實現了工具腳本。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、linux內存管理機制

Linux的內存管理機制,網上的資料很多,就不多談了。本文只對一些基本的概念囉嗦幾句。

虛擬內存:linux上每個進程都有一個虛擬的地址空間,這個虛擬的地址空間大小在ps命令裡體現為VSZ,在top命令裡體現為VIRT。這空間可以很大,單個進程的VSZ超出整個系統的內存,也是很常見的。

常駐內存:只有實際要發生訪問的內存,才會被映射到RAM上,在ps命令裡體現為RSS,在top命令裡體現為RES

如下圖所示,vpp的VSZ為99G(你看,任性吧。),RSS為787M。

(注:PS命令中內存基本單位是KB,B代表bit)

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

進程使用的內存,還有一種分法:私有內存和共享內存。

顧名思義,私有內存即是被該進程獨享的內存,共享內存是多個進程共享的內存,一般地,當多個進程依賴相同的鏈接庫時,鏈接庫也會被映射到每一個進程的地址空間裡。所以,即使RSS也未真正的反映進程到底佔用了系統多少內存資源。

綜上,測試linux系統上進程內存洩漏的一個基本思路為:

定期通過ps、cat proc/$pid/status、pmap –d $pid等命令,觀測進程的rss和私有內存的變化。如果兩者都在持續上漲,那麼該進程有很大嫌疑存在內存洩漏。如果只有其中之一在漲,需進一步使用定位方法(或者請求開發協助),最好能弄明白具體原因。

監測linux內存性能的命令有很多,除上文提到過的命令外,用戶態進程還有smaps,vmstat以及其他命令監測,內核一般是查看slabinfo。本文不介紹這些命令的詳細用法。

"

我下面這篇文章提供了一種輕巧的內存洩漏測試方法及其python實現,該方法在Lenovo Bamboo系統的驗收測試活動中得到過諸多檢驗,是一種易用有效的內存洩漏測試方法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

一、內存洩漏測試原理

1、內存洩漏的危害。

內存洩漏的危害不必多說,會導致系統的可用內存越來越少,影響系統長時間運行的穩定性。

2、常用的內存洩漏測試方法

一般而言,可概括為兩種思路:

1)內存分配、釋放工具檢查

如valgrind等內存測試工具。

2)Linux系統性能監測

如zabbix等linux性能監測工具,以及團隊自研的檢測linux性能的工具。

在方法一中,工具的原理一般是通過檢查當程序動態分配內存後,是否有釋放來判斷有沒有發生內存洩漏。其優點很明顯,發現洩漏時能很方便定位到代碼的具體哪個地方在洩漏內存。但缺點也很明顯:一是工具容易誤判,二是工具要干涉程序編譯過程,使得工具使用起來很麻煩。這兩個缺點對於黑盒測試人員來說尤其容易感受到。

其實,還有第三個缺點。作為測試人員,真正關心的難道是程序結束時內存有沒有free嗎?不然。絕大多數的進程原本就該持續運行永不結束(至少我們希望是這樣),測試人員真正關心的是進程所使用的內存是基本穩定的,還是持續增長的。如果是持續增長的,就有影響系統長時間運行穩定性的風險。

綜上, Bamboo OS測試人員根據方法二總結了內存洩漏測試方法,並利用python實現了工具腳本。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、linux內存管理機制

Linux的內存管理機制,網上的資料很多,就不多談了。本文只對一些基本的概念囉嗦幾句。

虛擬內存:linux上每個進程都有一個虛擬的地址空間,這個虛擬的地址空間大小在ps命令裡體現為VSZ,在top命令裡體現為VIRT。這空間可以很大,單個進程的VSZ超出整個系統的內存,也是很常見的。

常駐內存:只有實際要發生訪問的內存,才會被映射到RAM上,在ps命令裡體現為RSS,在top命令裡體現為RES

如下圖所示,vpp的VSZ為99G(你看,任性吧。),RSS為787M。

(注:PS命令中內存基本單位是KB,B代表bit)

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

進程使用的內存,還有一種分法:私有內存和共享內存。

顧名思義,私有內存即是被該進程獨享的內存,共享內存是多個進程共享的內存,一般地,當多個進程依賴相同的鏈接庫時,鏈接庫也會被映射到每一個進程的地址空間裡。所以,即使RSS也未真正的反映進程到底佔用了系統多少內存資源。

綜上,測試linux系統上進程內存洩漏的一個基本思路為:

定期通過ps、cat proc/$pid/status、pmap –d $pid等命令,觀測進程的rss和私有內存的變化。如果兩者都在持續上漲,那麼該進程有很大嫌疑存在內存洩漏。如果只有其中之一在漲,需進一步使用定位方法(或者請求開發協助),最好能弄明白具體原因。

監測linux內存性能的命令有很多,除上文提到過的命令外,用戶態進程還有smaps,vmstat以及其他命令監測,內核一般是查看slabinfo。本文不介紹這些命令的詳細用法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

二、Bamboo 系統內存洩漏檢測腳本的實現

1、設計測試方法

視對系統的瞭解程度,可以選擇性地

1)通過審閱設計文檔或歷史缺陷、與開發溝通交流,找出項目動態分配內存的地方;

2)設計測試步驟,測試步驟應當讓最終的狀態與初始狀態時一個狀態。比如,創建router ospf實例,進行實例的初始化和資源分配、協議交互後,又刪去了此實例,系統回到初始狀態;

3)反覆執行測試步驟並通過linux的命令觀察內存變化。如果rss和私有內存持續上漲,則有嫌疑出現了內存洩漏;

4)定位(或協調開發來定位)問題,可通過pmap命令的詳細信息對比、gdb調試、valgrind或其他工具來定位。

"

我下面這篇文章提供了一種輕巧的內存洩漏測試方法及其python實現,該方法在Lenovo Bamboo系統的驗收測試活動中得到過諸多檢驗,是一種易用有效的內存洩漏測試方法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

一、內存洩漏測試原理

1、內存洩漏的危害。

內存洩漏的危害不必多說,會導致系統的可用內存越來越少,影響系統長時間運行的穩定性。

2、常用的內存洩漏測試方法

一般而言,可概括為兩種思路:

1)內存分配、釋放工具檢查

如valgrind等內存測試工具。

2)Linux系統性能監測

如zabbix等linux性能監測工具,以及團隊自研的檢測linux性能的工具。

在方法一中,工具的原理一般是通過檢查當程序動態分配內存後,是否有釋放來判斷有沒有發生內存洩漏。其優點很明顯,發現洩漏時能很方便定位到代碼的具體哪個地方在洩漏內存。但缺點也很明顯:一是工具容易誤判,二是工具要干涉程序編譯過程,使得工具使用起來很麻煩。這兩個缺點對於黑盒測試人員來說尤其容易感受到。

其實,還有第三個缺點。作為測試人員,真正關心的難道是程序結束時內存有沒有free嗎?不然。絕大多數的進程原本就該持續運行永不結束(至少我們希望是這樣),測試人員真正關心的是進程所使用的內存是基本穩定的,還是持續增長的。如果是持續增長的,就有影響系統長時間運行穩定性的風險。

綜上, Bamboo OS測試人員根據方法二總結了內存洩漏測試方法,並利用python實現了工具腳本。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、linux內存管理機制

Linux的內存管理機制,網上的資料很多,就不多談了。本文只對一些基本的概念囉嗦幾句。

虛擬內存:linux上每個進程都有一個虛擬的地址空間,這個虛擬的地址空間大小在ps命令裡體現為VSZ,在top命令裡體現為VIRT。這空間可以很大,單個進程的VSZ超出整個系統的內存,也是很常見的。

常駐內存:只有實際要發生訪問的內存,才會被映射到RAM上,在ps命令裡體現為RSS,在top命令裡體現為RES

如下圖所示,vpp的VSZ為99G(你看,任性吧。),RSS為787M。

(注:PS命令中內存基本單位是KB,B代表bit)

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

進程使用的內存,還有一種分法:私有內存和共享內存。

顧名思義,私有內存即是被該進程獨享的內存,共享內存是多個進程共享的內存,一般地,當多個進程依賴相同的鏈接庫時,鏈接庫也會被映射到每一個進程的地址空間裡。所以,即使RSS也未真正的反映進程到底佔用了系統多少內存資源。

綜上,測試linux系統上進程內存洩漏的一個基本思路為:

定期通過ps、cat proc/$pid/status、pmap –d $pid等命令,觀測進程的rss和私有內存的變化。如果兩者都在持續上漲,那麼該進程有很大嫌疑存在內存洩漏。如果只有其中之一在漲,需進一步使用定位方法(或者請求開發協助),最好能弄明白具體原因。

監測linux內存性能的命令有很多,除上文提到過的命令外,用戶態進程還有smaps,vmstat以及其他命令監測,內核一般是查看slabinfo。本文不介紹這些命令的詳細用法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

二、Bamboo 系統內存洩漏檢測腳本的實現

1、設計測試方法

視對系統的瞭解程度,可以選擇性地

1)通過審閱設計文檔或歷史缺陷、與開發溝通交流,找出項目動態分配內存的地方;

2)設計測試步驟,測試步驟應當讓最終的狀態與初始狀態時一個狀態。比如,創建router ospf實例,進行實例的初始化和資源分配、協議交互後,又刪去了此實例,系統回到初始狀態;

3)反覆執行測試步驟並通過linux的命令觀察內存變化。如果rss和私有內存持續上漲,則有嫌疑出現了內存洩漏;

4)定位(或協調開發來定位)問題,可通過pmap命令的詳細信息對比、gdb調試、valgrind或其他工具來定位。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

2、實現內存拷機測試腳本

內存拷機腳本工具包含兩部分,memMonitor和mytest。

memMonitor是工作框架,依賴Bamboo系統的自動化測試平臺,該平臺能提供bamboos_ssh功能讓腳本可以創建一個Bamboo系統實例並在該系統執行命令。筆者提供的版本是通過命令行來獲取系統內存信息的,各功能函數通過分析字符串來獲取數據,讀者可以自行實現。內存監測結果的呈現可炫酷可簡易,讀者可自行實現。

memMonitor 的傳參mytest是一個函數,這個函數裡是測試人員設計的測試步驟(比如上文說過的創建和銷燬ospf實例),對於工具的使用人員來說,他不需要關心memMonitor內部實現機制,只要設計他個人的mytest就可以了。

memMonitor腳本的基本架構如下。

import bamboos_ssh

import re

import time

'''

本用例通過linux提供的ps和pmap命令監控Bamboo系統裡指定進程的內存變化。

'''

##--------------全局參數設置--設置檢測範圍-------------------------------##

processList = ['./omu','/bin/ffe/vpp/vpp','l3stackMain','srvc','nse','ospfd','nettool_server',

'infoc','ffe_mgmt','usermgr','nat','dhcpd','ntpd','bgpd','sysrepod']

##++++++++++++++++++++++++++++++++++++++++++++++++++++##

def memMonitor(targetSystemIP,psName,repeatRounds,mytest):

rssList = []

privateList = []

##-----------------------------初始化工作------------------------------------- -##

dut1_ssh = bamboos_ssh.bamboos_ssh(targetSystemIP)

print('\\n初始時完整獲取ps信息,找到目標進程的進程號,獲取該進程的pmap信息')

psAllInfo = dut1_ssh.exe_cmd( ['ps -aux'])

psID = getPsID(psName,psAllInfo)

psAllRssStart = getPsAllRss(processList,psAllInfo)

dut1_ssh.exe_cmd( ['pmap -d %s'%psID])

dut1_ssh.exe_cmd(['exit'])

##-----------------------------拷機過程-----------------------------------------##

##主循環多次執行測試員的拷機腳本,每次執行後獲取rss內存和private內存信息

for i in range(0,repeatRounds+1):

try:

if 0 == i:

print('\\n獲取初始內存信息')

else:

print('\\n第%d輪測試' % i)

mytest(dut1_ssh)

print('\\n第%d次獲取內存信息' % i)

rssMem = getRssMem(dut1_ssh,psID)

rssList.append(rssMem)

privateMem = getPrivateMem(dut1_ssh,psID)

privateList.append(int(privateMem))

dut1_ssh.exe_cmd(['exit'])

except BaseException as e:

print(e);print('第%d輪測試時異常終止了'%i);resultPrint(psName, rssList, privateList);break

##最後一輪測試時再次獲取ps信息,以及目標進程的pmap信息

print('\\n結束時完整獲取ps信息,以及目標進程的pmap信息')

psAllInfo = dut1_ssh.exe_cmd(['ps -aux'])

psAllRssEnd = getPsAllRss(processList,psAllInfo)

dut1_ssh.exe_cmd(['pmap -d %s' % psID])

dut1_ssh.exe_cmd(['exit'])

##-------------------顯示最終的監測結果------------------------------------------##

print('=========================拷機測試的結果=====================')

resultPrint(psName, rssList, privateList)

compareAllPsRss(processList, psAllRssStart, psAllRssEnd)

##-------------------清理測試環境,結束測試---------------------------------------##

dut1_ssh.close()

##++++++++++++++++++++++++++++++++++++++++++++##

def getPsID(psName,psInfo):

#根據PSInfo檢索出psID

# return psID

def getPsAllRss(psNameList,psAllInfo):

#通過psALLInfo檢索出所有ps的RSS並返回

# return psRssList

def getRssMem(dut1_ssh,psID):

#根據 'cat /proc/%s/status | grep VmRSS' 命令找出每一個ps的rss內存值

# return rssMem

def getPrivateMem(dut1_ssh,psID):

#根據 'pmap -d %s | grep mapped' 命令找出每一個ps的私有內存值

# return privateMem

def resultPrint(psName,rssList,privateList):

#根據需要輸出內存監測結果,可以是炫酷的圖形化輸出,也可以是簡易輸出,例如:

print('\\n進程%s的物理內存佔用趨勢為:'%psName)

print(rssList)

print('\\n進程%s的私有內存使用趨勢為:'%psName)

print(privateList)

def compareAllPsRss(processList,psAllRssStart,psAllRssEnd):

#對所有進程的一個輸出,可以是圖形化的,也可以是簡易的

"

我下面這篇文章提供了一種輕巧的內存洩漏測試方法及其python實現,該方法在Lenovo Bamboo系統的驗收測試活動中得到過諸多檢驗,是一種易用有效的內存洩漏測試方法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

一、內存洩漏測試原理

1、內存洩漏的危害。

內存洩漏的危害不必多說,會導致系統的可用內存越來越少,影響系統長時間運行的穩定性。

2、常用的內存洩漏測試方法

一般而言,可概括為兩種思路:

1)內存分配、釋放工具檢查

如valgrind等內存測試工具。

2)Linux系統性能監測

如zabbix等linux性能監測工具,以及團隊自研的檢測linux性能的工具。

在方法一中,工具的原理一般是通過檢查當程序動態分配內存後,是否有釋放來判斷有沒有發生內存洩漏。其優點很明顯,發現洩漏時能很方便定位到代碼的具體哪個地方在洩漏內存。但缺點也很明顯:一是工具容易誤判,二是工具要干涉程序編譯過程,使得工具使用起來很麻煩。這兩個缺點對於黑盒測試人員來說尤其容易感受到。

其實,還有第三個缺點。作為測試人員,真正關心的難道是程序結束時內存有沒有free嗎?不然。絕大多數的進程原本就該持續運行永不結束(至少我們希望是這樣),測試人員真正關心的是進程所使用的內存是基本穩定的,還是持續增長的。如果是持續增長的,就有影響系統長時間運行穩定性的風險。

綜上, Bamboo OS測試人員根據方法二總結了內存洩漏測試方法,並利用python實現了工具腳本。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、linux內存管理機制

Linux的內存管理機制,網上的資料很多,就不多談了。本文只對一些基本的概念囉嗦幾句。

虛擬內存:linux上每個進程都有一個虛擬的地址空間,這個虛擬的地址空間大小在ps命令裡體現為VSZ,在top命令裡體現為VIRT。這空間可以很大,單個進程的VSZ超出整個系統的內存,也是很常見的。

常駐內存:只有實際要發生訪問的內存,才會被映射到RAM上,在ps命令裡體現為RSS,在top命令裡體現為RES

如下圖所示,vpp的VSZ為99G(你看,任性吧。),RSS為787M。

(注:PS命令中內存基本單位是KB,B代表bit)

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

進程使用的內存,還有一種分法:私有內存和共享內存。

顧名思義,私有內存即是被該進程獨享的內存,共享內存是多個進程共享的內存,一般地,當多個進程依賴相同的鏈接庫時,鏈接庫也會被映射到每一個進程的地址空間裡。所以,即使RSS也未真正的反映進程到底佔用了系統多少內存資源。

綜上,測試linux系統上進程內存洩漏的一個基本思路為:

定期通過ps、cat proc/$pid/status、pmap –d $pid等命令,觀測進程的rss和私有內存的變化。如果兩者都在持續上漲,那麼該進程有很大嫌疑存在內存洩漏。如果只有其中之一在漲,需進一步使用定位方法(或者請求開發協助),最好能弄明白具體原因。

監測linux內存性能的命令有很多,除上文提到過的命令外,用戶態進程還有smaps,vmstat以及其他命令監測,內核一般是查看slabinfo。本文不介紹這些命令的詳細用法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

二、Bamboo 系統內存洩漏檢測腳本的實現

1、設計測試方法

視對系統的瞭解程度,可以選擇性地

1)通過審閱設計文檔或歷史缺陷、與開發溝通交流,找出項目動態分配內存的地方;

2)設計測試步驟,測試步驟應當讓最終的狀態與初始狀態時一個狀態。比如,創建router ospf實例,進行實例的初始化和資源分配、協議交互後,又刪去了此實例,系統回到初始狀態;

3)反覆執行測試步驟並通過linux的命令觀察內存變化。如果rss和私有內存持續上漲,則有嫌疑出現了內存洩漏;

4)定位(或協調開發來定位)問題,可通過pmap命令的詳細信息對比、gdb調試、valgrind或其他工具來定位。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

2、實現內存拷機測試腳本

內存拷機腳本工具包含兩部分,memMonitor和mytest。

memMonitor是工作框架,依賴Bamboo系統的自動化測試平臺,該平臺能提供bamboos_ssh功能讓腳本可以創建一個Bamboo系統實例並在該系統執行命令。筆者提供的版本是通過命令行來獲取系統內存信息的,各功能函數通過分析字符串來獲取數據,讀者可以自行實現。內存監測結果的呈現可炫酷可簡易,讀者可自行實現。

memMonitor 的傳參mytest是一個函數,這個函數裡是測試人員設計的測試步驟(比如上文說過的創建和銷燬ospf實例),對於工具的使用人員來說,他不需要關心memMonitor內部實現機制,只要設計他個人的mytest就可以了。

memMonitor腳本的基本架構如下。

import bamboos_ssh

import re

import time

'''

本用例通過linux提供的ps和pmap命令監控Bamboo系統裡指定進程的內存變化。

'''

##--------------全局參數設置--設置檢測範圍-------------------------------##

processList = ['./omu','/bin/ffe/vpp/vpp','l3stackMain','srvc','nse','ospfd','nettool_server',

'infoc','ffe_mgmt','usermgr','nat','dhcpd','ntpd','bgpd','sysrepod']

##++++++++++++++++++++++++++++++++++++++++++++++++++++##

def memMonitor(targetSystemIP,psName,repeatRounds,mytest):

rssList = []

privateList = []

##-----------------------------初始化工作------------------------------------- -##

dut1_ssh = bamboos_ssh.bamboos_ssh(targetSystemIP)

print('\\n初始時完整獲取ps信息,找到目標進程的進程號,獲取該進程的pmap信息')

psAllInfo = dut1_ssh.exe_cmd( ['ps -aux'])

psID = getPsID(psName,psAllInfo)

psAllRssStart = getPsAllRss(processList,psAllInfo)

dut1_ssh.exe_cmd( ['pmap -d %s'%psID])

dut1_ssh.exe_cmd(['exit'])

##-----------------------------拷機過程-----------------------------------------##

##主循環多次執行測試員的拷機腳本,每次執行後獲取rss內存和private內存信息

for i in range(0,repeatRounds+1):

try:

if 0 == i:

print('\\n獲取初始內存信息')

else:

print('\\n第%d輪測試' % i)

mytest(dut1_ssh)

print('\\n第%d次獲取內存信息' % i)

rssMem = getRssMem(dut1_ssh,psID)

rssList.append(rssMem)

privateMem = getPrivateMem(dut1_ssh,psID)

privateList.append(int(privateMem))

dut1_ssh.exe_cmd(['exit'])

except BaseException as e:

print(e);print('第%d輪測試時異常終止了'%i);resultPrint(psName, rssList, privateList);break

##最後一輪測試時再次獲取ps信息,以及目標進程的pmap信息

print('\\n結束時完整獲取ps信息,以及目標進程的pmap信息')

psAllInfo = dut1_ssh.exe_cmd(['ps -aux'])

psAllRssEnd = getPsAllRss(processList,psAllInfo)

dut1_ssh.exe_cmd(['pmap -d %s' % psID])

dut1_ssh.exe_cmd(['exit'])

##-------------------顯示最終的監測結果------------------------------------------##

print('=========================拷機測試的結果=====================')

resultPrint(psName, rssList, privateList)

compareAllPsRss(processList, psAllRssStart, psAllRssEnd)

##-------------------清理測試環境,結束測試---------------------------------------##

dut1_ssh.close()

##++++++++++++++++++++++++++++++++++++++++++++##

def getPsID(psName,psInfo):

#根據PSInfo檢索出psID

# return psID

def getPsAllRss(psNameList,psAllInfo):

#通過psALLInfo檢索出所有ps的RSS並返回

# return psRssList

def getRssMem(dut1_ssh,psID):

#根據 'cat /proc/%s/status | grep VmRSS' 命令找出每一個ps的rss內存值

# return rssMem

def getPrivateMem(dut1_ssh,psID):

#根據 'pmap -d %s | grep mapped' 命令找出每一個ps的私有內存值

# return privateMem

def resultPrint(psName,rssList,privateList):

#根據需要輸出內存監測結果,可以是炫酷的圖形化輸出,也可以是簡易輸出,例如:

print('\\n進程%s的物理內存佔用趨勢為:'%psName)

print(rssList)

print('\\n進程%s的私有內存使用趨勢為:'%psName)

print(privateList)

def compareAllPsRss(processList,psAllRssStart,psAllRssEnd):

#對所有進程的一個輸出,可以是圖形化的,也可以是簡易的

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、使用內存拷機測試腳本

使用實例:

1)測試同學懷疑ntp特性在配置本地時鐘存在內存洩漏,所以設置主要監測的進程是ntpd

2)在mytest函數裡定義了將反覆執行的命令。

def mytest(dut1_ssh):

for i in range(0,10):

dut1_ssh.config(['ntp-service refclock-master 9'])

time.sleep(2)

dut1_ssh.config(['no ntp-service refclock-master'])

3)主程序將反覆執行mytest,並週期性的查看ntpd進程的rss內存和私有內存信息

4)主程序在初始時和結束時獲取了一次ntpd進程的完整pmap信息,方便在懷疑ntpd存在內存洩漏時進行進一步的定位分析。

"

我下面這篇文章提供了一種輕巧的內存洩漏測試方法及其python實現,該方法在Lenovo Bamboo系統的驗收測試活動中得到過諸多檢驗,是一種易用有效的內存洩漏測試方法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

一、內存洩漏測試原理

1、內存洩漏的危害。

內存洩漏的危害不必多說,會導致系統的可用內存越來越少,影響系統長時間運行的穩定性。

2、常用的內存洩漏測試方法

一般而言,可概括為兩種思路:

1)內存分配、釋放工具檢查

如valgrind等內存測試工具。

2)Linux系統性能監測

如zabbix等linux性能監測工具,以及團隊自研的檢測linux性能的工具。

在方法一中,工具的原理一般是通過檢查當程序動態分配內存後,是否有釋放來判斷有沒有發生內存洩漏。其優點很明顯,發現洩漏時能很方便定位到代碼的具體哪個地方在洩漏內存。但缺點也很明顯:一是工具容易誤判,二是工具要干涉程序編譯過程,使得工具使用起來很麻煩。這兩個缺點對於黑盒測試人員來說尤其容易感受到。

其實,還有第三個缺點。作為測試人員,真正關心的難道是程序結束時內存有沒有free嗎?不然。絕大多數的進程原本就該持續運行永不結束(至少我們希望是這樣),測試人員真正關心的是進程所使用的內存是基本穩定的,還是持續增長的。如果是持續增長的,就有影響系統長時間運行穩定性的風險。

綜上, Bamboo OS測試人員根據方法二總結了內存洩漏測試方法,並利用python實現了工具腳本。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、linux內存管理機制

Linux的內存管理機制,網上的資料很多,就不多談了。本文只對一些基本的概念囉嗦幾句。

虛擬內存:linux上每個進程都有一個虛擬的地址空間,這個虛擬的地址空間大小在ps命令裡體現為VSZ,在top命令裡體現為VIRT。這空間可以很大,單個進程的VSZ超出整個系統的內存,也是很常見的。

常駐內存:只有實際要發生訪問的內存,才會被映射到RAM上,在ps命令裡體現為RSS,在top命令裡體現為RES

如下圖所示,vpp的VSZ為99G(你看,任性吧。),RSS為787M。

(注:PS命令中內存基本單位是KB,B代表bit)

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

進程使用的內存,還有一種分法:私有內存和共享內存。

顧名思義,私有內存即是被該進程獨享的內存,共享內存是多個進程共享的內存,一般地,當多個進程依賴相同的鏈接庫時,鏈接庫也會被映射到每一個進程的地址空間裡。所以,即使RSS也未真正的反映進程到底佔用了系統多少內存資源。

綜上,測試linux系統上進程內存洩漏的一個基本思路為:

定期通過ps、cat proc/$pid/status、pmap –d $pid等命令,觀測進程的rss和私有內存的變化。如果兩者都在持續上漲,那麼該進程有很大嫌疑存在內存洩漏。如果只有其中之一在漲,需進一步使用定位方法(或者請求開發協助),最好能弄明白具體原因。

監測linux內存性能的命令有很多,除上文提到過的命令外,用戶態進程還有smaps,vmstat以及其他命令監測,內核一般是查看slabinfo。本文不介紹這些命令的詳細用法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

二、Bamboo 系統內存洩漏檢測腳本的實現

1、設計測試方法

視對系統的瞭解程度,可以選擇性地

1)通過審閱設計文檔或歷史缺陷、與開發溝通交流,找出項目動態分配內存的地方;

2)設計測試步驟,測試步驟應當讓最終的狀態與初始狀態時一個狀態。比如,創建router ospf實例,進行實例的初始化和資源分配、協議交互後,又刪去了此實例,系統回到初始狀態;

3)反覆執行測試步驟並通過linux的命令觀察內存變化。如果rss和私有內存持續上漲,則有嫌疑出現了內存洩漏;

4)定位(或協調開發來定位)問題,可通過pmap命令的詳細信息對比、gdb調試、valgrind或其他工具來定位。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

2、實現內存拷機測試腳本

內存拷機腳本工具包含兩部分,memMonitor和mytest。

memMonitor是工作框架,依賴Bamboo系統的自動化測試平臺,該平臺能提供bamboos_ssh功能讓腳本可以創建一個Bamboo系統實例並在該系統執行命令。筆者提供的版本是通過命令行來獲取系統內存信息的,各功能函數通過分析字符串來獲取數據,讀者可以自行實現。內存監測結果的呈現可炫酷可簡易,讀者可自行實現。

memMonitor 的傳參mytest是一個函數,這個函數裡是測試人員設計的測試步驟(比如上文說過的創建和銷燬ospf實例),對於工具的使用人員來說,他不需要關心memMonitor內部實現機制,只要設計他個人的mytest就可以了。

memMonitor腳本的基本架構如下。

import bamboos_ssh

import re

import time

'''

本用例通過linux提供的ps和pmap命令監控Bamboo系統裡指定進程的內存變化。

'''

##--------------全局參數設置--設置檢測範圍-------------------------------##

processList = ['./omu','/bin/ffe/vpp/vpp','l3stackMain','srvc','nse','ospfd','nettool_server',

'infoc','ffe_mgmt','usermgr','nat','dhcpd','ntpd','bgpd','sysrepod']

##++++++++++++++++++++++++++++++++++++++++++++++++++++##

def memMonitor(targetSystemIP,psName,repeatRounds,mytest):

rssList = []

privateList = []

##-----------------------------初始化工作------------------------------------- -##

dut1_ssh = bamboos_ssh.bamboos_ssh(targetSystemIP)

print('\\n初始時完整獲取ps信息,找到目標進程的進程號,獲取該進程的pmap信息')

psAllInfo = dut1_ssh.exe_cmd( ['ps -aux'])

psID = getPsID(psName,psAllInfo)

psAllRssStart = getPsAllRss(processList,psAllInfo)

dut1_ssh.exe_cmd( ['pmap -d %s'%psID])

dut1_ssh.exe_cmd(['exit'])

##-----------------------------拷機過程-----------------------------------------##

##主循環多次執行測試員的拷機腳本,每次執行後獲取rss內存和private內存信息

for i in range(0,repeatRounds+1):

try:

if 0 == i:

print('\\n獲取初始內存信息')

else:

print('\\n第%d輪測試' % i)

mytest(dut1_ssh)

print('\\n第%d次獲取內存信息' % i)

rssMem = getRssMem(dut1_ssh,psID)

rssList.append(rssMem)

privateMem = getPrivateMem(dut1_ssh,psID)

privateList.append(int(privateMem))

dut1_ssh.exe_cmd(['exit'])

except BaseException as e:

print(e);print('第%d輪測試時異常終止了'%i);resultPrint(psName, rssList, privateList);break

##最後一輪測試時再次獲取ps信息,以及目標進程的pmap信息

print('\\n結束時完整獲取ps信息,以及目標進程的pmap信息')

psAllInfo = dut1_ssh.exe_cmd(['ps -aux'])

psAllRssEnd = getPsAllRss(processList,psAllInfo)

dut1_ssh.exe_cmd(['pmap -d %s' % psID])

dut1_ssh.exe_cmd(['exit'])

##-------------------顯示最終的監測結果------------------------------------------##

print('=========================拷機測試的結果=====================')

resultPrint(psName, rssList, privateList)

compareAllPsRss(processList, psAllRssStart, psAllRssEnd)

##-------------------清理測試環境,結束測試---------------------------------------##

dut1_ssh.close()

##++++++++++++++++++++++++++++++++++++++++++++##

def getPsID(psName,psInfo):

#根據PSInfo檢索出psID

# return psID

def getPsAllRss(psNameList,psAllInfo):

#通過psALLInfo檢索出所有ps的RSS並返回

# return psRssList

def getRssMem(dut1_ssh,psID):

#根據 'cat /proc/%s/status | grep VmRSS' 命令找出每一個ps的rss內存值

# return rssMem

def getPrivateMem(dut1_ssh,psID):

#根據 'pmap -d %s | grep mapped' 命令找出每一個ps的私有內存值

# return privateMem

def resultPrint(psName,rssList,privateList):

#根據需要輸出內存監測結果,可以是炫酷的圖形化輸出,也可以是簡易輸出,例如:

print('\\n進程%s的物理內存佔用趨勢為:'%psName)

print(rssList)

print('\\n進程%s的私有內存使用趨勢為:'%psName)

print(privateList)

def compareAllPsRss(processList,psAllRssStart,psAllRssEnd):

#對所有進程的一個輸出,可以是圖形化的,也可以是簡易的

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、使用內存拷機測試腳本

使用實例:

1)測試同學懷疑ntp特性在配置本地時鐘存在內存洩漏,所以設置主要監測的進程是ntpd

2)在mytest函數裡定義了將反覆執行的命令。

def mytest(dut1_ssh):

for i in range(0,10):

dut1_ssh.config(['ntp-service refclock-master 9'])

time.sleep(2)

dut1_ssh.config(['no ntp-service refclock-master'])

3)主程序將反覆執行mytest,並週期性的查看ntpd進程的rss內存和私有內存信息

4)主程序在初始時和結束時獲取了一次ntpd進程的完整pmap信息,方便在懷疑ntpd存在內存洩漏時進行進一步的定位分析。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

運行結果:

主要的結果如下圖所示:(筆者使用的版本當前未將數據圖形化)

可以看到,ntpd的rss內存增長顯著,私有內存也呈一直上漲趨勢。所以,ntpd有很大嫌疑存在內存洩漏。

"

我下面這篇文章提供了一種輕巧的內存洩漏測試方法及其python實現,該方法在Lenovo Bamboo系統的驗收測試活動中得到過諸多檢驗,是一種易用有效的內存洩漏測試方法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

一、內存洩漏測試原理

1、內存洩漏的危害。

內存洩漏的危害不必多說,會導致系統的可用內存越來越少,影響系統長時間運行的穩定性。

2、常用的內存洩漏測試方法

一般而言,可概括為兩種思路:

1)內存分配、釋放工具檢查

如valgrind等內存測試工具。

2)Linux系統性能監測

如zabbix等linux性能監測工具,以及團隊自研的檢測linux性能的工具。

在方法一中,工具的原理一般是通過檢查當程序動態分配內存後,是否有釋放來判斷有沒有發生內存洩漏。其優點很明顯,發現洩漏時能很方便定位到代碼的具體哪個地方在洩漏內存。但缺點也很明顯:一是工具容易誤判,二是工具要干涉程序編譯過程,使得工具使用起來很麻煩。這兩個缺點對於黑盒測試人員來說尤其容易感受到。

其實,還有第三個缺點。作為測試人員,真正關心的難道是程序結束時內存有沒有free嗎?不然。絕大多數的進程原本就該持續運行永不結束(至少我們希望是這樣),測試人員真正關心的是進程所使用的內存是基本穩定的,還是持續增長的。如果是持續增長的,就有影響系統長時間運行穩定性的風險。

綜上, Bamboo OS測試人員根據方法二總結了內存洩漏測試方法,並利用python實現了工具腳本。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、linux內存管理機制

Linux的內存管理機制,網上的資料很多,就不多談了。本文只對一些基本的概念囉嗦幾句。

虛擬內存:linux上每個進程都有一個虛擬的地址空間,這個虛擬的地址空間大小在ps命令裡體現為VSZ,在top命令裡體現為VIRT。這空間可以很大,單個進程的VSZ超出整個系統的內存,也是很常見的。

常駐內存:只有實際要發生訪問的內存,才會被映射到RAM上,在ps命令裡體現為RSS,在top命令裡體現為RES

如下圖所示,vpp的VSZ為99G(你看,任性吧。),RSS為787M。

(注:PS命令中內存基本單位是KB,B代表bit)

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

進程使用的內存,還有一種分法:私有內存和共享內存。

顧名思義,私有內存即是被該進程獨享的內存,共享內存是多個進程共享的內存,一般地,當多個進程依賴相同的鏈接庫時,鏈接庫也會被映射到每一個進程的地址空間裡。所以,即使RSS也未真正的反映進程到底佔用了系統多少內存資源。

綜上,測試linux系統上進程內存洩漏的一個基本思路為:

定期通過ps、cat proc/$pid/status、pmap –d $pid等命令,觀測進程的rss和私有內存的變化。如果兩者都在持續上漲,那麼該進程有很大嫌疑存在內存洩漏。如果只有其中之一在漲,需進一步使用定位方法(或者請求開發協助),最好能弄明白具體原因。

監測linux內存性能的命令有很多,除上文提到過的命令外,用戶態進程還有smaps,vmstat以及其他命令監測,內核一般是查看slabinfo。本文不介紹這些命令的詳細用法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

二、Bamboo 系統內存洩漏檢測腳本的實現

1、設計測試方法

視對系統的瞭解程度,可以選擇性地

1)通過審閱設計文檔或歷史缺陷、與開發溝通交流,找出項目動態分配內存的地方;

2)設計測試步驟,測試步驟應當讓最終的狀態與初始狀態時一個狀態。比如,創建router ospf實例,進行實例的初始化和資源分配、協議交互後,又刪去了此實例,系統回到初始狀態;

3)反覆執行測試步驟並通過linux的命令觀察內存變化。如果rss和私有內存持續上漲,則有嫌疑出現了內存洩漏;

4)定位(或協調開發來定位)問題,可通過pmap命令的詳細信息對比、gdb調試、valgrind或其他工具來定位。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

2、實現內存拷機測試腳本

內存拷機腳本工具包含兩部分,memMonitor和mytest。

memMonitor是工作框架,依賴Bamboo系統的自動化測試平臺,該平臺能提供bamboos_ssh功能讓腳本可以創建一個Bamboo系統實例並在該系統執行命令。筆者提供的版本是通過命令行來獲取系統內存信息的,各功能函數通過分析字符串來獲取數據,讀者可以自行實現。內存監測結果的呈現可炫酷可簡易,讀者可自行實現。

memMonitor 的傳參mytest是一個函數,這個函數裡是測試人員設計的測試步驟(比如上文說過的創建和銷燬ospf實例),對於工具的使用人員來說,他不需要關心memMonitor內部實現機制,只要設計他個人的mytest就可以了。

memMonitor腳本的基本架構如下。

import bamboos_ssh

import re

import time

'''

本用例通過linux提供的ps和pmap命令監控Bamboo系統裡指定進程的內存變化。

'''

##--------------全局參數設置--設置檢測範圍-------------------------------##

processList = ['./omu','/bin/ffe/vpp/vpp','l3stackMain','srvc','nse','ospfd','nettool_server',

'infoc','ffe_mgmt','usermgr','nat','dhcpd','ntpd','bgpd','sysrepod']

##++++++++++++++++++++++++++++++++++++++++++++++++++++##

def memMonitor(targetSystemIP,psName,repeatRounds,mytest):

rssList = []

privateList = []

##-----------------------------初始化工作------------------------------------- -##

dut1_ssh = bamboos_ssh.bamboos_ssh(targetSystemIP)

print('\\n初始時完整獲取ps信息,找到目標進程的進程號,獲取該進程的pmap信息')

psAllInfo = dut1_ssh.exe_cmd( ['ps -aux'])

psID = getPsID(psName,psAllInfo)

psAllRssStart = getPsAllRss(processList,psAllInfo)

dut1_ssh.exe_cmd( ['pmap -d %s'%psID])

dut1_ssh.exe_cmd(['exit'])

##-----------------------------拷機過程-----------------------------------------##

##主循環多次執行測試員的拷機腳本,每次執行後獲取rss內存和private內存信息

for i in range(0,repeatRounds+1):

try:

if 0 == i:

print('\\n獲取初始內存信息')

else:

print('\\n第%d輪測試' % i)

mytest(dut1_ssh)

print('\\n第%d次獲取內存信息' % i)

rssMem = getRssMem(dut1_ssh,psID)

rssList.append(rssMem)

privateMem = getPrivateMem(dut1_ssh,psID)

privateList.append(int(privateMem))

dut1_ssh.exe_cmd(['exit'])

except BaseException as e:

print(e);print('第%d輪測試時異常終止了'%i);resultPrint(psName, rssList, privateList);break

##最後一輪測試時再次獲取ps信息,以及目標進程的pmap信息

print('\\n結束時完整獲取ps信息,以及目標進程的pmap信息')

psAllInfo = dut1_ssh.exe_cmd(['ps -aux'])

psAllRssEnd = getPsAllRss(processList,psAllInfo)

dut1_ssh.exe_cmd(['pmap -d %s' % psID])

dut1_ssh.exe_cmd(['exit'])

##-------------------顯示最終的監測結果------------------------------------------##

print('=========================拷機測試的結果=====================')

resultPrint(psName, rssList, privateList)

compareAllPsRss(processList, psAllRssStart, psAllRssEnd)

##-------------------清理測試環境,結束測試---------------------------------------##

dut1_ssh.close()

##++++++++++++++++++++++++++++++++++++++++++++##

def getPsID(psName,psInfo):

#根據PSInfo檢索出psID

# return psID

def getPsAllRss(psNameList,psAllInfo):

#通過psALLInfo檢索出所有ps的RSS並返回

# return psRssList

def getRssMem(dut1_ssh,psID):

#根據 'cat /proc/%s/status | grep VmRSS' 命令找出每一個ps的rss內存值

# return rssMem

def getPrivateMem(dut1_ssh,psID):

#根據 'pmap -d %s | grep mapped' 命令找出每一個ps的私有內存值

# return privateMem

def resultPrint(psName,rssList,privateList):

#根據需要輸出內存監測結果,可以是炫酷的圖形化輸出,也可以是簡易輸出,例如:

print('\\n進程%s的物理內存佔用趨勢為:'%psName)

print(rssList)

print('\\n進程%s的私有內存使用趨勢為:'%psName)

print(privateList)

def compareAllPsRss(processList,psAllRssStart,psAllRssEnd):

#對所有進程的一個輸出,可以是圖形化的,也可以是簡易的

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、使用內存拷機測試腳本

使用實例:

1)測試同學懷疑ntp特性在配置本地時鐘存在內存洩漏,所以設置主要監測的進程是ntpd

2)在mytest函數裡定義了將反覆執行的命令。

def mytest(dut1_ssh):

for i in range(0,10):

dut1_ssh.config(['ntp-service refclock-master 9'])

time.sleep(2)

dut1_ssh.config(['no ntp-service refclock-master'])

3)主程序將反覆執行mytest,並週期性的查看ntpd進程的rss內存和私有內存信息

4)主程序在初始時和結束時獲取了一次ntpd進程的完整pmap信息,方便在懷疑ntpd存在內存洩漏時進行進一步的定位分析。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

運行結果:

主要的結果如下圖所示:(筆者使用的版本當前未將數據圖形化)

可以看到,ntpd的rss內存增長顯著,私有內存也呈一直上漲趨勢。所以,ntpd有很大嫌疑存在內存洩漏。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

因為想進一步分析內存的變化,所以對比了程序執行前後ntpd的pmap信息。可以看到在結束時,pmap信息裡多了更多的大小為4K的分頁。測試人員將這一信息提供給開發同學,開發同學據此很快找到了內存洩漏的原因在於NTP記錄日誌後沒有釋放分頁。

"

我下面這篇文章提供了一種輕巧的內存洩漏測試方法及其python實現,該方法在Lenovo Bamboo系統的驗收測試活動中得到過諸多檢驗,是一種易用有效的內存洩漏測試方法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

一、內存洩漏測試原理

1、內存洩漏的危害。

內存洩漏的危害不必多說,會導致系統的可用內存越來越少,影響系統長時間運行的穩定性。

2、常用的內存洩漏測試方法

一般而言,可概括為兩種思路:

1)內存分配、釋放工具檢查

如valgrind等內存測試工具。

2)Linux系統性能監測

如zabbix等linux性能監測工具,以及團隊自研的檢測linux性能的工具。

在方法一中,工具的原理一般是通過檢查當程序動態分配內存後,是否有釋放來判斷有沒有發生內存洩漏。其優點很明顯,發現洩漏時能很方便定位到代碼的具體哪個地方在洩漏內存。但缺點也很明顯:一是工具容易誤判,二是工具要干涉程序編譯過程,使得工具使用起來很麻煩。這兩個缺點對於黑盒測試人員來說尤其容易感受到。

其實,還有第三個缺點。作為測試人員,真正關心的難道是程序結束時內存有沒有free嗎?不然。絕大多數的進程原本就該持續運行永不結束(至少我們希望是這樣),測試人員真正關心的是進程所使用的內存是基本穩定的,還是持續增長的。如果是持續增長的,就有影響系統長時間運行穩定性的風險。

綜上, Bamboo OS測試人員根據方法二總結了內存洩漏測試方法,並利用python實現了工具腳本。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、linux內存管理機制

Linux的內存管理機制,網上的資料很多,就不多談了。本文只對一些基本的概念囉嗦幾句。

虛擬內存:linux上每個進程都有一個虛擬的地址空間,這個虛擬的地址空間大小在ps命令裡體現為VSZ,在top命令裡體現為VIRT。這空間可以很大,單個進程的VSZ超出整個系統的內存,也是很常見的。

常駐內存:只有實際要發生訪問的內存,才會被映射到RAM上,在ps命令裡體現為RSS,在top命令裡體現為RES

如下圖所示,vpp的VSZ為99G(你看,任性吧。),RSS為787M。

(注:PS命令中內存基本單位是KB,B代表bit)

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

進程使用的內存,還有一種分法:私有內存和共享內存。

顧名思義,私有內存即是被該進程獨享的內存,共享內存是多個進程共享的內存,一般地,當多個進程依賴相同的鏈接庫時,鏈接庫也會被映射到每一個進程的地址空間裡。所以,即使RSS也未真正的反映進程到底佔用了系統多少內存資源。

綜上,測試linux系統上進程內存洩漏的一個基本思路為:

定期通過ps、cat proc/$pid/status、pmap –d $pid等命令,觀測進程的rss和私有內存的變化。如果兩者都在持續上漲,那麼該進程有很大嫌疑存在內存洩漏。如果只有其中之一在漲,需進一步使用定位方法(或者請求開發協助),最好能弄明白具體原因。

監測linux內存性能的命令有很多,除上文提到過的命令外,用戶態進程還有smaps,vmstat以及其他命令監測,內核一般是查看slabinfo。本文不介紹這些命令的詳細用法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

二、Bamboo 系統內存洩漏檢測腳本的實現

1、設計測試方法

視對系統的瞭解程度,可以選擇性地

1)通過審閱設計文檔或歷史缺陷、與開發溝通交流,找出項目動態分配內存的地方;

2)設計測試步驟,測試步驟應當讓最終的狀態與初始狀態時一個狀態。比如,創建router ospf實例,進行實例的初始化和資源分配、協議交互後,又刪去了此實例,系統回到初始狀態;

3)反覆執行測試步驟並通過linux的命令觀察內存變化。如果rss和私有內存持續上漲,則有嫌疑出現了內存洩漏;

4)定位(或協調開發來定位)問題,可通過pmap命令的詳細信息對比、gdb調試、valgrind或其他工具來定位。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

2、實現內存拷機測試腳本

內存拷機腳本工具包含兩部分,memMonitor和mytest。

memMonitor是工作框架,依賴Bamboo系統的自動化測試平臺,該平臺能提供bamboos_ssh功能讓腳本可以創建一個Bamboo系統實例並在該系統執行命令。筆者提供的版本是通過命令行來獲取系統內存信息的,各功能函數通過分析字符串來獲取數據,讀者可以自行實現。內存監測結果的呈現可炫酷可簡易,讀者可自行實現。

memMonitor 的傳參mytest是一個函數,這個函數裡是測試人員設計的測試步驟(比如上文說過的創建和銷燬ospf實例),對於工具的使用人員來說,他不需要關心memMonitor內部實現機制,只要設計他個人的mytest就可以了。

memMonitor腳本的基本架構如下。

import bamboos_ssh

import re

import time

'''

本用例通過linux提供的ps和pmap命令監控Bamboo系統裡指定進程的內存變化。

'''

##--------------全局參數設置--設置檢測範圍-------------------------------##

processList = ['./omu','/bin/ffe/vpp/vpp','l3stackMain','srvc','nse','ospfd','nettool_server',

'infoc','ffe_mgmt','usermgr','nat','dhcpd','ntpd','bgpd','sysrepod']

##++++++++++++++++++++++++++++++++++++++++++++++++++++##

def memMonitor(targetSystemIP,psName,repeatRounds,mytest):

rssList = []

privateList = []

##-----------------------------初始化工作------------------------------------- -##

dut1_ssh = bamboos_ssh.bamboos_ssh(targetSystemIP)

print('\\n初始時完整獲取ps信息,找到目標進程的進程號,獲取該進程的pmap信息')

psAllInfo = dut1_ssh.exe_cmd( ['ps -aux'])

psID = getPsID(psName,psAllInfo)

psAllRssStart = getPsAllRss(processList,psAllInfo)

dut1_ssh.exe_cmd( ['pmap -d %s'%psID])

dut1_ssh.exe_cmd(['exit'])

##-----------------------------拷機過程-----------------------------------------##

##主循環多次執行測試員的拷機腳本,每次執行後獲取rss內存和private內存信息

for i in range(0,repeatRounds+1):

try:

if 0 == i:

print('\\n獲取初始內存信息')

else:

print('\\n第%d輪測試' % i)

mytest(dut1_ssh)

print('\\n第%d次獲取內存信息' % i)

rssMem = getRssMem(dut1_ssh,psID)

rssList.append(rssMem)

privateMem = getPrivateMem(dut1_ssh,psID)

privateList.append(int(privateMem))

dut1_ssh.exe_cmd(['exit'])

except BaseException as e:

print(e);print('第%d輪測試時異常終止了'%i);resultPrint(psName, rssList, privateList);break

##最後一輪測試時再次獲取ps信息,以及目標進程的pmap信息

print('\\n結束時完整獲取ps信息,以及目標進程的pmap信息')

psAllInfo = dut1_ssh.exe_cmd(['ps -aux'])

psAllRssEnd = getPsAllRss(processList,psAllInfo)

dut1_ssh.exe_cmd(['pmap -d %s' % psID])

dut1_ssh.exe_cmd(['exit'])

##-------------------顯示最終的監測結果------------------------------------------##

print('=========================拷機測試的結果=====================')

resultPrint(psName, rssList, privateList)

compareAllPsRss(processList, psAllRssStart, psAllRssEnd)

##-------------------清理測試環境,結束測試---------------------------------------##

dut1_ssh.close()

##++++++++++++++++++++++++++++++++++++++++++++##

def getPsID(psName,psInfo):

#根據PSInfo檢索出psID

# return psID

def getPsAllRss(psNameList,psAllInfo):

#通過psALLInfo檢索出所有ps的RSS並返回

# return psRssList

def getRssMem(dut1_ssh,psID):

#根據 'cat /proc/%s/status | grep VmRSS' 命令找出每一個ps的rss內存值

# return rssMem

def getPrivateMem(dut1_ssh,psID):

#根據 'pmap -d %s | grep mapped' 命令找出每一個ps的私有內存值

# return privateMem

def resultPrint(psName,rssList,privateList):

#根據需要輸出內存監測結果,可以是炫酷的圖形化輸出,也可以是簡易輸出,例如:

print('\\n進程%s的物理內存佔用趨勢為:'%psName)

print(rssList)

print('\\n進程%s的私有內存使用趨勢為:'%psName)

print(privateList)

def compareAllPsRss(processList,psAllRssStart,psAllRssEnd):

#對所有進程的一個輸出,可以是圖形化的,也可以是簡易的

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、使用內存拷機測試腳本

使用實例:

1)測試同學懷疑ntp特性在配置本地時鐘存在內存洩漏,所以設置主要監測的進程是ntpd

2)在mytest函數裡定義了將反覆執行的命令。

def mytest(dut1_ssh):

for i in range(0,10):

dut1_ssh.config(['ntp-service refclock-master 9'])

time.sleep(2)

dut1_ssh.config(['no ntp-service refclock-master'])

3)主程序將反覆執行mytest,並週期性的查看ntpd進程的rss內存和私有內存信息

4)主程序在初始時和結束時獲取了一次ntpd進程的完整pmap信息,方便在懷疑ntpd存在內存洩漏時進行進一步的定位分析。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

運行結果:

主要的結果如下圖所示:(筆者使用的版本當前未將數據圖形化)

可以看到,ntpd的rss內存增長顯著,私有內存也呈一直上漲趨勢。所以,ntpd有很大嫌疑存在內存洩漏。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

因為想進一步分析內存的變化,所以對比了程序執行前後ntpd的pmap信息。可以看到在結束時,pmap信息裡多了更多的大小為4K的分頁。測試人員將這一信息提供給開發同學,開發同學據此很快找到了內存洩漏的原因在於NTP記錄日誌後沒有釋放分頁。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

請關注+私信回覆:“學習”就可以免費拿到軟件測試學習資料

"

我下面這篇文章提供了一種輕巧的內存洩漏測試方法及其python實現,該方法在Lenovo Bamboo系統的驗收測試活動中得到過諸多檢驗,是一種易用有效的內存洩漏測試方法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

一、內存洩漏測試原理

1、內存洩漏的危害。

內存洩漏的危害不必多說,會導致系統的可用內存越來越少,影響系統長時間運行的穩定性。

2、常用的內存洩漏測試方法

一般而言,可概括為兩種思路:

1)內存分配、釋放工具檢查

如valgrind等內存測試工具。

2)Linux系統性能監測

如zabbix等linux性能監測工具,以及團隊自研的檢測linux性能的工具。

在方法一中,工具的原理一般是通過檢查當程序動態分配內存後,是否有釋放來判斷有沒有發生內存洩漏。其優點很明顯,發現洩漏時能很方便定位到代碼的具體哪個地方在洩漏內存。但缺點也很明顯:一是工具容易誤判,二是工具要干涉程序編譯過程,使得工具使用起來很麻煩。這兩個缺點對於黑盒測試人員來說尤其容易感受到。

其實,還有第三個缺點。作為測試人員,真正關心的難道是程序結束時內存有沒有free嗎?不然。絕大多數的進程原本就該持續運行永不結束(至少我們希望是這樣),測試人員真正關心的是進程所使用的內存是基本穩定的,還是持續增長的。如果是持續增長的,就有影響系統長時間運行穩定性的風險。

綜上, Bamboo OS測試人員根據方法二總結了內存洩漏測試方法,並利用python實現了工具腳本。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、linux內存管理機制

Linux的內存管理機制,網上的資料很多,就不多談了。本文只對一些基本的概念囉嗦幾句。

虛擬內存:linux上每個進程都有一個虛擬的地址空間,這個虛擬的地址空間大小在ps命令裡體現為VSZ,在top命令裡體現為VIRT。這空間可以很大,單個進程的VSZ超出整個系統的內存,也是很常見的。

常駐內存:只有實際要發生訪問的內存,才會被映射到RAM上,在ps命令裡體現為RSS,在top命令裡體現為RES

如下圖所示,vpp的VSZ為99G(你看,任性吧。),RSS為787M。

(注:PS命令中內存基本單位是KB,B代表bit)

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

進程使用的內存,還有一種分法:私有內存和共享內存。

顧名思義,私有內存即是被該進程獨享的內存,共享內存是多個進程共享的內存,一般地,當多個進程依賴相同的鏈接庫時,鏈接庫也會被映射到每一個進程的地址空間裡。所以,即使RSS也未真正的反映進程到底佔用了系統多少內存資源。

綜上,測試linux系統上進程內存洩漏的一個基本思路為:

定期通過ps、cat proc/$pid/status、pmap –d $pid等命令,觀測進程的rss和私有內存的變化。如果兩者都在持續上漲,那麼該進程有很大嫌疑存在內存洩漏。如果只有其中之一在漲,需進一步使用定位方法(或者請求開發協助),最好能弄明白具體原因。

監測linux內存性能的命令有很多,除上文提到過的命令外,用戶態進程還有smaps,vmstat以及其他命令監測,內核一般是查看slabinfo。本文不介紹這些命令的詳細用法。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

二、Bamboo 系統內存洩漏檢測腳本的實現

1、設計測試方法

視對系統的瞭解程度,可以選擇性地

1)通過審閱設計文檔或歷史缺陷、與開發溝通交流,找出項目動態分配內存的地方;

2)設計測試步驟,測試步驟應當讓最終的狀態與初始狀態時一個狀態。比如,創建router ospf實例,進行實例的初始化和資源分配、協議交互後,又刪去了此實例,系統回到初始狀態;

3)反覆執行測試步驟並通過linux的命令觀察內存變化。如果rss和私有內存持續上漲,則有嫌疑出現了內存洩漏;

4)定位(或協調開發來定位)問題,可通過pmap命令的詳細信息對比、gdb調試、valgrind或其他工具來定位。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

2、實現內存拷機測試腳本

內存拷機腳本工具包含兩部分,memMonitor和mytest。

memMonitor是工作框架,依賴Bamboo系統的自動化測試平臺,該平臺能提供bamboos_ssh功能讓腳本可以創建一個Bamboo系統實例並在該系統執行命令。筆者提供的版本是通過命令行來獲取系統內存信息的,各功能函數通過分析字符串來獲取數據,讀者可以自行實現。內存監測結果的呈現可炫酷可簡易,讀者可自行實現。

memMonitor 的傳參mytest是一個函數,這個函數裡是測試人員設計的測試步驟(比如上文說過的創建和銷燬ospf實例),對於工具的使用人員來說,他不需要關心memMonitor內部實現機制,只要設計他個人的mytest就可以了。

memMonitor腳本的基本架構如下。

import bamboos_ssh

import re

import time

'''

本用例通過linux提供的ps和pmap命令監控Bamboo系統裡指定進程的內存變化。

'''

##--------------全局參數設置--設置檢測範圍-------------------------------##

processList = ['./omu','/bin/ffe/vpp/vpp','l3stackMain','srvc','nse','ospfd','nettool_server',

'infoc','ffe_mgmt','usermgr','nat','dhcpd','ntpd','bgpd','sysrepod']

##++++++++++++++++++++++++++++++++++++++++++++++++++++##

def memMonitor(targetSystemIP,psName,repeatRounds,mytest):

rssList = []

privateList = []

##-----------------------------初始化工作------------------------------------- -##

dut1_ssh = bamboos_ssh.bamboos_ssh(targetSystemIP)

print('\\n初始時完整獲取ps信息,找到目標進程的進程號,獲取該進程的pmap信息')

psAllInfo = dut1_ssh.exe_cmd( ['ps -aux'])

psID = getPsID(psName,psAllInfo)

psAllRssStart = getPsAllRss(processList,psAllInfo)

dut1_ssh.exe_cmd( ['pmap -d %s'%psID])

dut1_ssh.exe_cmd(['exit'])

##-----------------------------拷機過程-----------------------------------------##

##主循環多次執行測試員的拷機腳本,每次執行後獲取rss內存和private內存信息

for i in range(0,repeatRounds+1):

try:

if 0 == i:

print('\\n獲取初始內存信息')

else:

print('\\n第%d輪測試' % i)

mytest(dut1_ssh)

print('\\n第%d次獲取內存信息' % i)

rssMem = getRssMem(dut1_ssh,psID)

rssList.append(rssMem)

privateMem = getPrivateMem(dut1_ssh,psID)

privateList.append(int(privateMem))

dut1_ssh.exe_cmd(['exit'])

except BaseException as e:

print(e);print('第%d輪測試時異常終止了'%i);resultPrint(psName, rssList, privateList);break

##最後一輪測試時再次獲取ps信息,以及目標進程的pmap信息

print('\\n結束時完整獲取ps信息,以及目標進程的pmap信息')

psAllInfo = dut1_ssh.exe_cmd(['ps -aux'])

psAllRssEnd = getPsAllRss(processList,psAllInfo)

dut1_ssh.exe_cmd(['pmap -d %s' % psID])

dut1_ssh.exe_cmd(['exit'])

##-------------------顯示最終的監測結果------------------------------------------##

print('=========================拷機測試的結果=====================')

resultPrint(psName, rssList, privateList)

compareAllPsRss(processList, psAllRssStart, psAllRssEnd)

##-------------------清理測試環境,結束測試---------------------------------------##

dut1_ssh.close()

##++++++++++++++++++++++++++++++++++++++++++++##

def getPsID(psName,psInfo):

#根據PSInfo檢索出psID

# return psID

def getPsAllRss(psNameList,psAllInfo):

#通過psALLInfo檢索出所有ps的RSS並返回

# return psRssList

def getRssMem(dut1_ssh,psID):

#根據 'cat /proc/%s/status | grep VmRSS' 命令找出每一個ps的rss內存值

# return rssMem

def getPrivateMem(dut1_ssh,psID):

#根據 'pmap -d %s | grep mapped' 命令找出每一個ps的私有內存值

# return privateMem

def resultPrint(psName,rssList,privateList):

#根據需要輸出內存監測結果,可以是炫酷的圖形化輸出,也可以是簡易輸出,例如:

print('\\n進程%s的物理內存佔用趨勢為:'%psName)

print(rssList)

print('\\n進程%s的私有內存使用趨勢為:'%psName)

print(privateList)

def compareAllPsRss(processList,psAllRssStart,psAllRssEnd):

#對所有進程的一個輸出,可以是圖形化的,也可以是簡易的

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

3、使用內存拷機測試腳本

使用實例:

1)測試同學懷疑ntp特性在配置本地時鐘存在內存洩漏,所以設置主要監測的進程是ntpd

2)在mytest函數裡定義了將反覆執行的命令。

def mytest(dut1_ssh):

for i in range(0,10):

dut1_ssh.config(['ntp-service refclock-master 9'])

time.sleep(2)

dut1_ssh.config(['no ntp-service refclock-master'])

3)主程序將反覆執行mytest,並週期性的查看ntpd進程的rss內存和私有內存信息

4)主程序在初始時和結束時獲取了一次ntpd進程的完整pmap信息,方便在懷疑ntpd存在內存洩漏時進行進一步的定位分析。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

運行結果:

主要的結果如下圖所示:(筆者使用的版本當前未將數據圖形化)

可以看到,ntpd的rss內存增長顯著,私有內存也呈一直上漲趨勢。所以,ntpd有很大嫌疑存在內存洩漏。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

因為想進一步分析內存的變化,所以對比了程序執行前後ntpd的pmap信息。可以看到在結束時,pmap信息裡多了更多的大小為4K的分頁。測試人員將這一信息提供給開發同學,開發同學據此很快找到了內存洩漏的原因在於NTP記錄日誌後沒有釋放分頁。

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

請關注+私信回覆:“學習”就可以免費拿到軟件測試學習資料

怎樣用Python去實現內存洩露測試?一次Linux內存洩露實例分析

"

相關推薦

推薦中...