Python腳本實現(xiàn)內(nèi)存泄漏測試的方法及解決過程,針對這個問題,這篇文章詳細介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
創(chuàng)新互聯(lián)長期為近1000家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為德興企業(yè)提供專業(yè)的成都網(wǎng)站制作、成都網(wǎng)站建設(shè),德興網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
我下面這篇文章提供了一種輕巧的內(nèi)存泄漏測試方法及其python實現(xiàn),該方法在Lenovo Bamboo系統(tǒng)的驗收測試活動中得到過諸多檢驗,是一種易用有效的內(nèi)存泄漏測試方法。
一、內(nèi)存泄漏測試原理
1、內(nèi)存泄漏的危害。
內(nèi)存泄漏的危害不必多說,會導(dǎo)致系統(tǒng)的可用內(nèi)存越來越少,影響系統(tǒng)長時間運行的穩(wěn)定性。
2、常用的內(nèi)存泄漏測試方法
一般而言,可概括為兩種思路:
1)內(nèi)存分配、釋放工具檢查
如valgrind等內(nèi)存測試工具。
2)Linux系統(tǒng)性能監(jiān)測
如zabbix等linux性能監(jiān)測工具,以及團隊自研的檢測linux性能的工具。
在方法一中,工具的原理一般是通過檢查當(dāng)程序動態(tài)分配內(nèi)存后,是否有釋放來判斷有沒有發(fā)生內(nèi)存泄漏。其優(yōu)點很明顯,發(fā)現(xiàn)泄漏時能很方便定位到代碼的具體哪個地方在泄漏內(nèi)存。但缺點也很明顯:一是工具容易誤判,二是工具要干涉程序編譯過程,使得工具使用起來很麻煩。這兩個缺點對于黑盒測試人員來說尤其容易感受到。
其實,還有第三個缺點。作為測試人員,真正關(guān)心的難道是程序結(jié)束時內(nèi)存有沒有free嗎?不然。絕大多數(shù)的進程原本就該持續(xù)運行永不結(jié)束(至少我們希望是這樣),測試人員真正關(guān)心的是進程所使用的內(nèi)存是基本穩(wěn)定的,還是持續(xù)增長的。如果是持續(xù)增長的,就有影響系統(tǒng)長時間運行穩(wěn)定性的風(fēng)險。
綜上, Bamboo OS測試人員根據(jù)方法二總結(jié)了內(nèi)存泄漏測試方法,并利用python實現(xiàn)了工具腳本。
3、linux內(nèi)存管理機制
Linux的內(nèi)存管理機制,網(wǎng)上的資料很多,就不多談了。本文只對一些基本的概念啰嗦幾句。
虛擬內(nèi)存:linux上每個進程都有一個虛擬的地址空間,這個虛擬的地址空間大小在ps命令里體現(xiàn)為VSZ,在top命令里體現(xiàn)為VIRT。這空間可以很大,單個進程的VSZ超出整個系統(tǒng)的內(nèi)存,也是很常見的。
常駐內(nèi)存:只有實際要發(fā)生訪問的內(nèi)存,才會被映射到RAM上,在ps命令里體現(xiàn)為RSS,在top命令里體現(xiàn)為RES
如下圖所示,vpp的VSZ為99G(你看,任性。),RSS為787M。
(注:PS命令中內(nèi)存基本單位是KB,B代表bit)

進程使用的內(nèi)存,還有一種分法:私有內(nèi)存和共享內(nèi)存。
顧名思義,私有內(nèi)存即是被該進程獨享的內(nèi)存,共享內(nèi)存是多個進程共享的內(nèi)存,一般地,當(dāng)多個進程依賴相同的鏈接庫時,鏈接庫也會被映射到每一個進程的地址空間里。所以,即使RSS也未真正的反映進程到底占用了系統(tǒng)多少內(nèi)存資源。
綜上,測試linux系統(tǒng)上進程內(nèi)存泄漏的一個基本思路為:
定期通過ps、cat proc/$pid/status、pmap –d $pid等命令,觀測進程的rss和私有內(nèi)存的變化。如果兩者都在持續(xù)上漲,那么該進程有很大嫌疑存在內(nèi)存泄漏。如果只有其中之一在漲,需進一步使用定位方法(或者請求開發(fā)協(xié)助),最好能弄明白具體原因。
監(jiān)測linux內(nèi)存性能的命令有很多,除上文提到過的命令外,用戶態(tài)進程還有smaps,vmstat以及其他命令監(jiān)測,內(nèi)核一般是查看slabinfo。本文不介紹這些命令的詳細用法。
二、Bamboo 系統(tǒng)內(nèi)存泄漏檢測腳本的實現(xiàn)
1、設(shè)計測試方法
視對系統(tǒng)的了解程度,可以選擇性地
1)通過審閱設(shè)計文檔或歷史缺陷、與開發(fā)溝通交流,找出項目動態(tài)分配內(nèi)存的地方;
2)設(shè)計測試步驟,測試步驟應(yīng)當(dāng)讓最終的狀態(tài)與初始狀態(tài)時一個狀態(tài)。比如,創(chuàng)建router ospf實例,進行實例的初始化和資源分配、協(xié)議交互后,又刪去了此實例,系統(tǒng)回到初始狀態(tài);
3)反復(fù)執(zhí)行測試步驟并通過linux的命令觀察內(nèi)存變化。如果rss和私有內(nèi)存持續(xù)上漲,則有嫌疑出現(xiàn)了內(nèi)存泄漏;
4)定位(或協(xié)調(diào)開發(fā)來定位)問題,可通過pmap命令的詳細信息對比、gdb調(diào)試、valgrind或其他工具來定位。
2、實現(xiàn)內(nèi)存拷機測試腳本
內(nèi)存拷機腳本工具包含兩部分,memMonitor和mytest。
memMonitor是工作框架,依賴Bamboo系統(tǒng)的自動化測試平臺,該平臺能提供bamboos_ssh功能讓腳本可以創(chuàng)建一個Bamboo系統(tǒng)實例并在該系統(tǒng)執(zhí)行命令。筆者提供的版本是通過命令行來獲取系統(tǒng)內(nèi)存信息的,各功能函數(shù)通過分析字符串來獲取數(shù)據(jù),讀者可以自行實現(xiàn)。內(nèi)存監(jiān)測結(jié)果的呈現(xiàn)可炫酷可簡易,讀者可自行實現(xiàn)。
memMonitor 的傳參mytest是一個函數(shù),這個函數(shù)里是測試人員設(shè)計的測試步驟(比如上文說過的創(chuàng)建和銷毀ospf實例),對于工具的使用人員來說,他不需要關(guān)心memMonitor內(nèi)部實現(xiàn)機制,只要設(shè)計他個人的mytest就可以了。
memMonitor腳本的基本架構(gòu)如下。
import bamboos_ssh
import re
import time
'''
本用例通過linux提供的ps和pmap命令監(jiān)控Bamboo系統(tǒng)里指定進程的內(nèi)存變化。
'''
##--------------全局參數(shù)設(shè)置--設(shè)置檢測范圍-------------------------------##
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信息,找到目標(biāo)進程的進程號,獲取該進程的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'])
##-----------------------------拷機過程-----------------------------------------##
##主循環(huán)多次執(zhí)行測試員的拷機腳本,每次執(zhí)行后獲取rss內(nèi)存和private內(nèi)存信息
for i in range(0,repeatRounds+1):
try:
if 0 == i:
print('\n獲取初始內(nèi)存信息')
else:
print('\n第%d輪測試' % i)
mytest(dut1_ssh)
print('\n第%d次獲取內(nèi)存信息' % 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信息,以及目標(biāo)進程的pmap信息
print('\n結(jié)束時完整獲取ps信息,以及目標(biāo)進程的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'])
##-------------------顯示最終的監(jiān)測結(jié)果------------------------------------------##
print('=========================拷機測試的結(jié)果=====================')
resultPrint(psName, rssList, privateList)
compareAllPsRss(processList, psAllRssStart, psAllRssEnd)
##-------------------清理測試環(huán)境,結(jié)束測試---------------------------------------##
dut1_ssh.close()
##++++++++++++++++++++++++++++++++++++++++++++##
def getPsID(psName,psInfo):
#根據(jù)PSInfo檢索出psID
# return psID
def getPsAllRss(psNameList,psAllInfo):
#通過psALLInfo檢索出所有ps的RSS并返回
# return psRssList
def getRssMem(dut1_ssh,psID):
#根據(jù) 'cat /proc/%s/status | grep VmRSS' 命令找出每一個ps的rss內(nèi)存值
# return rssMem
def getPrivateMem(dut1_ssh,psID):
#根據(jù) 'pmap -d %s | grep mapped' 命令找出每一個ps的私有內(nèi)存值
# return privateMem
def resultPrint(psName,rssList,privateList):
#根據(jù)需要輸出內(nèi)存監(jiān)測結(jié)果,可以是炫酷的圖形化輸出,也可以是簡易輸出,例如:
print('\n進程%s的物理內(nèi)存占用趨勢為:'%psName)
print(rssList)
print('\n進程%s的私有內(nèi)存使用趨勢為:'%psName)
print(privateList)
def compareAllPsRss(processList,psAllRssStart,psAllRssEnd):
#對所有進程的一個輸出,可以是圖形化的,也可以是簡易的
3、使用內(nèi)存拷機測試腳本
使用實例:
1)測試同學(xué)懷疑ntp特性在配置本地時鐘存在內(nèi)存泄漏,所以設(shè)置主要監(jiān)測的進程是ntpd
2)在mytest函數(shù)里定義了將反復(fù)執(zhí)行的命令。
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)主程序?qū)⒎磸?fù)執(zhí)行mytest,并周期性的查看ntpd進程的rss內(nèi)存和私有內(nèi)存信息
4)主程序在初始時和結(jié)束時獲取了一次ntpd進程的完整pmap信息,方便在懷疑ntpd存在內(nèi)存泄漏時進行進一步的定位分析。
運行結(jié)果:
主要的結(jié)果如下圖所示:(筆者使用的版本當(dāng)前未將數(shù)據(jù)圖形化)
可以看到,ntpd的rss內(nèi)存增長顯著,私有內(nèi)存也呈一直上漲趨勢。所以,ntpd有很大嫌疑存在內(nèi)存泄漏。

因為想進一步分析內(nèi)存的變化,所以對比了程序執(zhí)行前后ntpd的pmap信息。可以看到在結(jié)束時,pmap信息里多了更多的大小為4K的分頁。測試人員將這一信息提供給開發(fā)同學(xué),開發(fā)同學(xué)據(jù)此很快找到了內(nèi)存泄漏的原因在于NTP記錄日志后沒有釋放分頁。

關(guān)于Python腳本實現(xiàn)內(nèi)存泄漏測試的方法及解決過程問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識。
當(dāng)前標(biāo)題:Python腳本實現(xiàn)內(nèi)存泄漏測試的方法及解決過程
標(biāo)題鏈接:http://chinadenli.net/article0/phdcio.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、品牌網(wǎng)站設(shè)計、標(biāo)簽優(yōu)化、企業(yè)建站、自適應(yīng)網(wǎng)站、ChatGPT
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)