溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python流程控制常用工具詳解

發(fā)布時(shí)間:2020-10-05 10:15:48 來(lái)源:腳本之家 閱讀:144 作者:yaominghui 欄目:開(kāi)發(fā)技術(shù)

在我們的工作中,我們使用ddagent ver。5作為收集工具,收集和報(bào)告托管服務(wù)器的性能指標(biāo),并對(duì)ddagent進(jìn)行一定程度的定制。經(jīng)過(guò)多次功能迭代,發(fā)現(xiàn)一批在線運(yùn)行時(shí)間長(zhǎng)的托管服務(wù)器占用了太多內(nèi)存。分析問(wèn)題機(jī)器上進(jìn)程樹(shù)中每個(gè)節(jié)點(diǎn)的占用情況,可以看出ddagent集合進(jìn)程的內(nèi)存占用仍然很高。

我們將學(xué)習(xí)最基本的流程控制工具,比如

if 條件判斷for 循環(huán)while 循環(huán)

作為保證業(yè)務(wù)系統(tǒng)穩(wěn)定運(yùn)行的監(jiān)控組件,存在內(nèi)存泄漏,這自然是非常嚴(yán)重的,所以我們開(kāi)始了我們的“故障排除之旅”。

if-elif-else 判斷

Python流程控制常用工具詳解

分析

有很多工具可以分析和導(dǎo)出Python程序的內(nèi)存狀態(tài)。在這里,我們使用pyrasite,它可以附加到正在運(yùn)行的Python程序,生成內(nèi)存快照,并檢查當(dāng)前哪些對(duì)象類型占用了多少內(nèi)存,并從大到小排序。

使用命令非常簡(jiǎn)單: pyrasite-memory-viewer <PID>,同時(shí)會(huì)生成一份快照文件: /tmp/pyrasite-<PID>-objects.json。

由于無(wú)法提供真實(shí)的生產(chǎn)數(shù)據(jù),下面提到的所有數(shù)據(jù)都來(lái)自問(wèn)題版本在測(cè)試環(huán)境中運(yùn)行12小時(shí)后的采樣。

在pyrasite提供的Cui視圖中,我們可以清楚地看到字典類型的對(duì)象實(shí)例占用的內(nèi)存最多,達(dá)到3.4mb,有6621個(gè)實(shí)例:

Python流程控制常用工具詳解

while 循環(huán)

While循環(huán)也是一種常見(jiàn)的循環(huán)方式。這種循環(huán)通常以循環(huán)體類或條件方式結(jié)束。它不可能無(wú)限期地進(jìn)行下去。

Python流程控制常用工具詳解

對(duì)于泄漏情況,我們有以下事實(shí)和猜測(cè):

一個(gè)或多個(gè)位置持續(xù)創(chuàng)建空字典對(duì)象,并且無(wú)法回收它們,從而導(dǎo)致內(nèi)存泄漏內(nèi)存泄漏量隨時(shí)間而增加。在索引收集業(yè)務(wù)中,泄漏很可能是在每個(gè)收集過(guò)程中引起的,并在間隔期之后重復(fù)觸發(fā)我們看不到當(dāng)前依賴的ddagent版本存在尚未關(guān)閉的相關(guān)問(wèn)題,這可能是在我們的定制過(guò)程中引入的錯(cuò)誤

[
 [
 [".../embedded/lib/python2.7/threading.py",774,"__bootstrap","self.__bootstrap_inner()"],
 [".../embedded/lib/python2.7/threading.py",801,"__bootstrap_inner","self.run()"],
 [".../modules/monitor/bot/schedule.py",51,"run","task.run()"],
 [".../modules/monitor/bot/task.py",50,"run","super(RepeatTask, self).run()"],
 [".../modules/monitor/bot/task.py",18,"run","self.check()"],
 [".../modules/monitor/checks/collector.py",223,"wrapper","_check.run()"],
 [".../modules/monitor/checks/__init__.py",630,"run","self._roll_up_instance_metadata()"],
 [".../modules/monitor/checks/__init__.py",498,"_roll_up_instance_metadata","dict((k, v) for (k, v) in self._instance_metadata))"],
 [".../modules/monitor/tracer.py",33,"__init__","self.trace_info = traceback.extract_stack()"]
 ],
 [
 [".../embedded/lib/python2.7/threading.py",774,"__bootstrap","self.__bootstrap_inner()"],
 [".../embedded/lib/python2.7/threading.py",801,"__bootstrap_inner","self.run()"],
 [".../modules/monitor/bot/schedule.py",51,"run","task.run()"],
 [".../modules/monitor/bot/task.py",50,"run","super(RepeatTask, self).run()"],
 [".../modules/monitor/bot/task.py",18,"run","self.check()"],
 [".../modules/monitor/checks/collector.py",223,"wrapper","_check.run()"],
 [".../modules/monitor/checks/__init__.py",630,"run","self._roll_up_instance_metadata()"],
 [".../modules/monitor/checks/__init__.py",498,"_roll_up_instance_metadata","dict((k, v) for (k, v) in self._instance_metadata))"],
 [".../modules/monitor/tracer.py",33,"__init__","self.trace_info = traceback.extract_stack()"]
 ],
 [
 [".../embedded/lib/python2.7/threading.py",774,"__bootstrap","self.__bootstrap_inner()"],
 [".../embedded/lib/python2.7/threading.py",801,"__bootstrap_inner","self.run()"],
 [".../modules/monitor/bot/schedule.py",51,"run","task.run()"],
 [".../modules/monitor/bot/task.py",50,"run","super(RepeatTask, self).run()"],
 [".../modules/monitor/bot/task.py",18,"run","self.check()"],
 [".../modules/monitor/checks/collector.py",223,"wrapper","_check.run()"],
 [".../modules/monitor/checks/__init__.py",630,"run","self._roll_up_instance_metadata()"],
 [".../modules/monitor/checks/__init__.py",498,"_roll_up_instance_metadata","dict((k, v) for (k, v) in self._instance_metadata))"],
 [".../modules/monitor/tracer.py",33,"__init__","self.trace_info = traceback.extract_stack()"]
 ],
...

重播

我們不提“做好設(shè)計(jì)審查和規(guī)范審查”、“加強(qiáng)試驗(yàn)階段質(zhì)量檢驗(yàn)工作”等“老生常談”,也值得我們反思。

要徹底防止和控制內(nèi)存泄漏幾乎是不可能的,像rust這樣的安全編程語(yǔ)言也不能保證程序不會(huì)泄漏內(nèi)存。

許多引發(fā)內(nèi)存不安全的行為,如數(shù)組訪問(wèn)越界、訪問(wèn)釋放后的內(nèi)存等,都可以通過(guò)制定更嚴(yán)格的編程模型(如rust提出的所有權(quán)+生命周期規(guī)則)甚至數(shù)據(jù)競(jìng)爭(zhēng)問(wèn)題來(lái)避免。

然而,觸發(fā)內(nèi)存泄漏的行為,如競(jìng)爭(zhēng)條件,需要開(kāi)發(fā)人員將開(kāi)發(fā)組件和業(yè)務(wù)規(guī)則結(jié)合起來(lái)。設(shè)想一個(gè)需要手動(dòng)觸發(fā)刷新的數(shù)據(jù)隊(duì)列。結(jié)果,我們?cè)谕扑蛿?shù)據(jù)時(shí)忘記調(diào)用它。這種內(nèi)存泄漏無(wú)法通過(guò)任何常規(guī)檢查規(guī)則來(lái)識(shí)別。

關(guān)鍵字函數(shù)是為了更形象地說(shuō)明傳入?yún)?shù)的位置和具體用法。如果一個(gè)函數(shù)有四個(gè)或五個(gè)參數(shù),而且一次傳入的參數(shù)太多,那么很難讓人眼花繚亂。如果key=value用于傳入。

總結(jié)

通過(guò)本節(jié)的學(xué)習(xí),我們了解了通過(guò)if else在不同條件下控制代碼流和執(zhí)行不同代碼。for/while和如何定義函數(shù)有兩種不同的循環(huán)方法,包括函數(shù)的返回值和參數(shù)傳遞方法、position參數(shù)傳遞和向函數(shù)傳遞參數(shù)時(shí)的key=value參數(shù)傳遞。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI