Python腳本實(shí)現(xiàn)內(nèi)存泄漏測(cè)試的方法及解決過(guò)程

Python腳本實(shí)現(xiàn)內(nèi)存泄漏測(cè)試的方法及解決過(guò)程,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

創(chuàng)新互聯(lián)長(zhǎng)期為近1000家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為德興企業(yè)提供專業(yè)的成都網(wǎng)站制作、成都網(wǎng)站建設(shè),德興網(wǎng)站改版等技術(shù)服務(wù)。擁有十年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。

我下面這篇文章提供了一種輕巧的內(nèi)存泄漏測(cè)試方法及其python實(shí)現(xiàn),該方法在Lenovo Bamboo系統(tǒng)的驗(yàn)收測(cè)試活動(dòng)中得到過(guò)諸多檢驗(yàn),是一種易用有效的內(nèi)存泄漏測(cè)試方法。

一、內(nèi)存泄漏測(cè)試原理

1、內(nèi)存泄漏的危害。

內(nèi)存泄漏的危害不必多說(shuō),會(huì)導(dǎo)致系統(tǒng)的可用內(nèi)存越來(lái)越少,影響系統(tǒng)長(zhǎng)時(shí)間運(yùn)行的穩(wěn)定性。

2、常用的內(nèi)存泄漏測(cè)試方法

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

1)內(nèi)存分配、釋放工具檢查

如valgrind等內(nèi)存測(cè)試工具。

2)Linux系統(tǒng)性能監(jiān)測(cè)

如zabbix等linux性能監(jiān)測(cè)工具,以及團(tuán)隊(duì)自研的檢測(cè)linux性能的工具。

在方法一中,工具的原理一般是通過(guò)檢查當(dāng)程序動(dòng)態(tài)分配內(nèi)存后,是否有釋放來(lái)判斷有沒(méi)有發(fā)生內(nèi)存泄漏。其優(yōu)點(diǎn)很明顯,發(fā)現(xiàn)泄漏時(shí)能很方便定位到代碼的具體哪個(gè)地方在泄漏內(nèi)存。但缺點(diǎn)也很明顯:一是工具容易誤判,二是工具要干涉程序編譯過(guò)程,使得工具使用起來(lái)很麻煩。這兩個(gè)缺點(diǎn)對(duì)于黑盒測(cè)試人員來(lái)說(shuō)尤其容易感受到。

其實(shí),還有第三個(gè)缺點(diǎn)。作為測(cè)試人員,真正關(guān)心的難道是程序結(jié)束時(shí)內(nèi)存有沒(méi)有free嗎?不然。絕大多數(shù)的進(jìn)程原本就該持續(xù)運(yùn)行永不結(jié)束(至少我們希望是這樣),測(cè)試人員真正關(guān)心的是進(jìn)程所使用的內(nèi)存是基本穩(wěn)定的,還是持續(xù)增長(zhǎng)的。如果是持續(xù)增長(zhǎng)的,就有影響系統(tǒng)長(zhǎng)時(shí)間運(yùn)行穩(wěn)定性的風(fēng)險(xiǎn)。

綜上, Bamboo OS測(cè)試人員根據(jù)方法二總結(jié)了內(nèi)存泄漏測(cè)試方法,并利用python實(shí)現(xiàn)了工具腳本。

3、linux內(nèi)存管理機(jī)制

Linux的內(nèi)存管理機(jī)制,網(wǎng)上的資料很多,就不多談了。本文只對(duì)一些基本的概念啰嗦幾句。

虛擬內(nèi)存:linux上每個(gè)進(jìn)程都有一個(gè)虛擬的地址空間,這個(gè)虛擬的地址空間大小在ps命令里體現(xiàn)為VSZ,在top命令里體現(xiàn)為VIRT。這空間可以很大,單個(gè)進(jìn)程的VSZ超出整個(gè)系統(tǒng)的內(nèi)存,也是很常見(jiàn)的。

常駐內(nèi)存:只有實(shí)際要發(fā)生訪問(wèn)的內(nèi)存,才會(huì)被映射到RAM上,在ps命令里體現(xiàn)為RSS,在top命令里體現(xiàn)為RES

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

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

Python腳本實(shí)現(xiàn)內(nèi)存泄漏測(cè)試的方法及解決過(guò)程

進(jìn)程使用的內(nèi)存,還有一種分法:私有內(nèi)存和共享內(nèi)存。

顧名思義,私有內(nèi)存即是被該進(jìn)程獨(dú)享的內(nèi)存,共享內(nèi)存是多個(gè)進(jìn)程共享的內(nèi)存,一般地,當(dāng)多個(gè)進(jìn)程依賴相同的鏈接庫(kù)時(shí),鏈接庫(kù)也會(huì)被映射到每一個(gè)進(jìn)程的地址空間里。所以,即使RSS也未真正的反映進(jìn)程到底占用了系統(tǒng)多少內(nèi)存資源。

綜上,測(cè)試linux系統(tǒng)上進(jìn)程內(nèi)存泄漏的一個(gè)基本思路為:

定期通過(guò)ps、cat proc/$pid/status、pmap –d $pid等命令,觀測(cè)進(jìn)程的rss和私有內(nèi)存的變化。如果兩者都在持續(xù)上漲,那么該進(jìn)程有很大嫌疑存在內(nèi)存泄漏。如果只有其中之一在漲,需進(jìn)一步使用定位方法(或者請(qǐng)求開(kāi)發(fā)協(xié)助),最好能弄明白具體原因。

監(jiān)測(cè)linux內(nèi)存性能的命令有很多,除上文提到過(guò)的命令外,用戶態(tài)進(jìn)程還有smaps,vmstat以及其他命令監(jiān)測(cè),內(nèi)核一般是查看slabinfo。本文不介紹這些命令的詳細(xì)用法。

二、Bamboo 系統(tǒng)內(nèi)存泄漏檢測(cè)腳本的實(shí)現(xiàn)

1、設(shè)計(jì)測(cè)試方法

視對(duì)系統(tǒng)的了解程度,可以選擇性地

1)通過(guò)審閱設(shè)計(jì)文檔或歷史缺陷、與開(kāi)發(fā)溝通交流,找出項(xiàng)目動(dòng)態(tài)分配內(nèi)存的地方;

2)設(shè)計(jì)測(cè)試步驟,測(cè)試步驟應(yīng)當(dāng)讓最終的狀態(tài)與初始狀態(tài)時(shí)一個(gè)狀態(tài)。比如,創(chuàng)建router ospf實(shí)例,進(jìn)行實(shí)例的初始化和資源分配、協(xié)議交互后,又刪去了此實(shí)例,系統(tǒng)回到初始狀態(tài);

3)反復(fù)執(zhí)行測(cè)試步驟并通過(guò)linux的命令觀察內(nèi)存變化。如果rss和私有內(nèi)存持續(xù)上漲,則有嫌疑出現(xiàn)了內(nèi)存泄漏;

4)定位(或協(xié)調(diào)開(kāi)發(fā)來(lái)定位)問(wèn)題,可通過(guò)pmap命令的詳細(xì)信息對(duì)比、gdb調(diào)試、valgrind或其他工具來(lái)定位。

2、實(shí)現(xiàn)內(nèi)存拷機(jī)測(cè)試腳本

內(nèi)存拷機(jī)腳本工具包含兩部分,memMonitor和mytest。

memMonitor是工作框架,依賴Bamboo系統(tǒng)的自動(dòng)化測(cè)試平臺(tái),該平臺(tái)能提供bamboos_ssh功能讓腳本可以創(chuàng)建一個(gè)Bamboo系統(tǒng)實(shí)例并在該系統(tǒng)執(zhí)行命令。筆者提供的版本是通過(guò)命令行來(lái)獲取系統(tǒng)內(nèi)存信息的,各功能函數(shù)通過(guò)分析字符串來(lái)獲取數(shù)據(jù),讀者可以自行實(shí)現(xiàn)。內(nèi)存監(jiān)測(cè)結(jié)果的呈現(xiàn)可炫酷可簡(jiǎn)易,讀者可自行實(shí)現(xiàn)。

memMonitor 的傳參mytest是一個(gè)函數(shù),這個(gè)函數(shù)里是測(cè)試人員設(shè)計(jì)的測(cè)試步驟(比如上文說(shuō)過(guò)的創(chuàng)建和銷毀ospf實(shí)例),對(duì)于工具的使用人員來(lái)說(shuō),他不需要關(guān)心memMonitor內(nèi)部實(shí)現(xiàn)機(jī)制,只要設(shè)計(jì)他個(gè)人的mytest就可以了。

memMonitor腳本的基本架構(gòu)如下。

import bamboos_ssh

import re

import time

'''

本用例通過(guò)linux提供的ps和pmap命令監(jiān)控Bamboo系統(tǒng)里指定進(jìn)程的內(nèi)存變化。

'''

##--------------全局參數(shù)設(shè)置--設(shè)置檢測(cè)范圍-------------------------------##

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初始時(shí)完整獲取ps信息,找到目標(biāo)進(jìn)程的進(jìn)程號(hào),獲取該進(jìn)程的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'])

   ##-----------------------------拷機(jī)過(guò)程-----------------------------------------##

   ##主循環(huán)多次執(zhí)行測(cè)試員的拷機(jī)腳本,每次執(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輪測(cè)試' % 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輪測(cè)試時(shí)異常終止了'%i);resultPrint(psName, rssList, privateList);break

   ##最后一輪測(cè)試時(shí)再次獲取ps信息,以及目標(biāo)進(jìn)程的pmap信息

   print('\n結(jié)束時(shí)完整獲取ps信息,以及目標(biāo)進(jìn)程的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)測(cè)結(jié)果------------------------------------------##

   print('=========================拷機(jī)測(cè)試的結(jié)果=====================')

   resultPrint(psName, rssList, privateList)

   compareAllPsRss(processList, psAllRssStart, psAllRssEnd)

   ##-------------------清理測(cè)試環(huán)境,結(jié)束測(cè)試---------------------------------------##

   dut1_ssh.close()

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

def getPsID(psName,psInfo):

#根據(jù)PSInfo檢索出psID

#    return psID

def getPsAllRss(psNameList,psAllInfo):

#通過(guò)psALLInfo檢索出所有ps的RSS并返回

#    return psRssList

def getRssMem(dut1_ssh,psID):

#根據(jù) 'cat /proc/%s/status | grep VmRSS' 命令找出每一個(gè)ps的rss內(nèi)存值

#    return rssMem

def getPrivateMem(dut1_ssh,psID):

#根據(jù) 'pmap -d %s | grep mapped' 命令找出每一個(gè)ps的私有內(nèi)存值

#    return privateMem

def resultPrint(psName,rssList,privateList):

#根據(jù)需要輸出內(nèi)存監(jiān)測(cè)結(jié)果,可以是炫酷的圖形化輸出,也可以是簡(jiǎn)易輸出,例如:

   print('\n進(jìn)程%s的物理內(nèi)存占用趨勢(shì)為:'%psName)

   print(rssList)

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

   print(privateList)

def compareAllPsRss(processList,psAllRssStart,psAllRssEnd):

#對(duì)所有進(jìn)程的一個(gè)輸出,可以是圖形化的,也可以是簡(jiǎn)易的

3、使用內(nèi)存拷機(jī)測(cè)試腳本

使用實(shí)例:

1)測(cè)試同學(xué)懷疑ntp特性在配置本地時(shí)鐘存在內(nèi)存泄漏,所以設(shè)置主要監(jiān)測(cè)的進(jì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進(jìn)程的rss內(nèi)存和私有內(nèi)存信息

4)主程序在初始時(shí)和結(jié)束時(shí)獲取了一次ntpd進(jìn)程的完整pmap信息,方便在懷疑ntpd存在內(nèi)存泄漏時(shí)進(jìn)行進(jìn)一步的定位分析。

運(yùn)行結(jié)果:

主要的結(jié)果如下圖所示:(筆者使用的版本當(dāng)前未將數(shù)據(jù)圖形化)

可以看到,ntpd的rss內(nèi)存增長(zhǎng)顯著,私有內(nèi)存也呈一直上漲趨勢(shì)。所以,ntpd有很大嫌疑存在內(nèi)存泄漏。

Python腳本實(shí)現(xiàn)內(nèi)存泄漏測(cè)試的方法及解決過(guò)程

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

Python腳本實(shí)現(xiàn)內(nèi)存泄漏測(cè)試的方法及解決過(guò)程

關(guān)于Python腳本實(shí)現(xiàn)內(nèi)存泄漏測(cè)試的方法及解決過(guò)程問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

當(dāng)前標(biāo)題:Python腳本實(shí)現(xiàn)內(nèi)存泄漏測(cè)試的方法及解決過(guò)程
標(biāo)題鏈接:http://bm7419.com/article0/phdcio.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、品牌網(wǎng)站設(shè)計(jì)標(biāo)簽優(yōu)化、企業(yè)建站自適應(yīng)網(wǎng)站、ChatGPT

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名