Python實(shí)現(xiàn)監(jiān)視程序的內(nèi)存使用情況
我們使用Python和它的數(shù)據(jù)處理庫(kù)套件(如panda和scikiti -learn)進(jìn)行大量數(shù)據(jù)處理時(shí)候,可能使用了大量的計(jì)算資源。如何監(jiān)視程序的內(nèi)存使用情況就顯得尤為重要。
1.詢問(wèn)操作系統(tǒng)
跟蹤內(nèi)存使用情況的最簡(jiǎn)單方法是使用操作系統(tǒng)本身。您可以使用top來(lái)提供您在一段時(shí)間內(nèi)使用的資源的概述?;蛘?,如果您想要現(xiàn)場(chǎng)檢查資源使用情況,您可以使用ps命令:
$ ps -m -o %cpu,%mem,command %CPU %MEM COMMAND 23.4 7.2 python analyze_data.py 0.0 0.0 bash
m標(biāo)志指示ps按照進(jìn)程使用最多內(nèi)存的順序顯示結(jié)果。o標(biāo)志控制顯示每個(gè)進(jìn)程的哪些屬性——在本例中是使用的CPU百分比、消耗的系統(tǒng)內(nèi)存百分比和正在執(zhí)行的進(jìn)程的命令行。
CPU百分比將一個(gè)完整的CPU核心計(jì)算為100%的使用率,因此如果您有一個(gè)4核的機(jī)器,可能會(huì)看到總計(jì)高達(dá)400%的CPU使用率。還有其他輸出選項(xiàng)用于顯示其他進(jìn)程屬性,以及用于控制顯示哪些進(jìn)程的ps的其他標(biāo)志。
結(jié)合一些創(chuàng)造性的shell腳本,可以編寫(xiě)一個(gè)監(jiān)視腳本,使用ps跟蹤任務(wù)的內(nèi)存使用情況。
2.tracemalloc
Python解釋器的操作中有大量的hooks,可以在Python代碼運(yùn)行時(shí)用于監(jiān)視和內(nèi)省。pdb使用這些鉤子來(lái)提供調(diào)試;覆蓋率也使用它們來(lái)提供測(cè)試覆蓋率。tracemalloc模塊還使用它們來(lái)提供一個(gè)了解內(nèi)存使用情況的窗口。
tracemalloc是在Python 3.4中添加的一個(gè)標(biāo)準(zhǔn)庫(kù)模塊,它跟蹤Python解釋器分配的每個(gè)單獨(dú)的內(nèi)存塊。tracemalloc能夠提供關(guān)于運(yùn)行Python進(jìn)程中內(nèi)存分配的非常細(xì)粒度的信息:
import tracemalloc
tracemalloc.start()
my_complex_analysis_method()
current, peak = tracemalloc.get_traced_memory()
print(f"Current memory usage is {current / 10**6}MB; Peak was {peak / 10**6}MB")
tracemalloc.stop()調(diào)用tracemplugin .start()啟動(dòng)跟蹤進(jìn)程。在進(jìn)行跟蹤時(shí),您可以詢問(wèn)分配了哪些內(nèi)容的詳細(xì)信息;在本例中,我們只要求當(dāng)前和峰值內(nèi)存分配。調(diào)用tracemplugin .stop()將刪除hook并清除已經(jīng)收集的任何跟蹤。
不過(guò),這種程度的細(xì)節(jié)是要付出代價(jià)的。tracemalloc將自己深深地注入到正在運(yùn)行的Python進(jìn)程中——正如您所預(yù)期的那樣,這會(huì)帶來(lái)性能損失。在我們的測(cè)試中,我們觀察到在運(yùn)行分析時(shí)使用tracemalloc的速度下降了30%。在分析單個(gè)進(jìn)程時(shí),這可能是可以的,但在生產(chǎn)中,您確實(shí)不希望僅僅為了監(jiān)視內(nèi)存使用情況而降低30%的性能。
3.抽樣
幸運(yùn)的是,Python標(biāo)準(zhǔn)庫(kù)提供了另一種觀察內(nèi)存使用情況的方法—resource模塊。resource模塊為程序分配的資源提供基本控制,包括內(nèi)存使用:
import resource usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
getrusage()的調(diào)用返回程序所使用的資源。常量RUSAGE_SELF表示我們只對(duì)這個(gè)進(jìn)程使用的資源感興趣,而不是它的子進(jìn)程。返回的對(duì)象是一個(gè)結(jié)構(gòu),它包含一系列操作系統(tǒng)資源,包括CPU時(shí)間、信號(hào)、上下文切換等;但就我們的目的而言,我們感興趣的是maxrss——最大駐留集大小——它是進(jìn)程當(dāng)前在RAM中持有的內(nèi)存量。
但是,與tracemalloc模塊不同的是,資源模塊不隨時(shí)間跟蹤使用情況—它只提供點(diǎn)采樣。因此,我們需要實(shí)現(xiàn)一種方法來(lái)隨時(shí)間對(duì)內(nèi)存使用情況進(jìn)行采樣。
首先,我們定義一個(gè)類來(lái)執(zhí)行內(nèi)存監(jiān)控:
import resource
from time import sleep
class MemoryMonitor:
def __init__(self):
self.keep_measuring = True
def measure_usage(self):
max_usage = 0
while self.keep_measuring:
max_usage = max(
max_usage,
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
)
sleep(0.1)
return max_usage在這個(gè)類的實(shí)例上調(diào)用measure_usage()時(shí),它將進(jìn)入一個(gè)循環(huán),每0.1秒測(cè)量一次內(nèi)存使用情況。將跟蹤內(nèi)存使用量的任何增加,并在循環(huán)退出時(shí)返回最大內(nèi)存分配。
但是什么告訴循環(huán)退出呢?我們?cè)谀睦镎{(diào)用被監(jiān)視的代碼?我們?cè)趩为?dú)的線程中完成。
from concurrent.futures import ThreadPoolExecutor
with ThreadPoolExecutor() as executor:
monitor = MemoryMonitor()
mem_thread = executor.submit(monitor.measure_usage)
try:
fn_thread = executor.submit(my_analysis_function)
result = fn_thread.result()
finally:
monitor.keep_measuring = False
max_usage = mem_thread.result()
print(f"Peak memory usage: {max_usage}")ThreadPoolExecutor為提交要在線程中執(zhí)行的任務(wù)提供了一種方便的方法。我們向執(zhí)行程序提交兩個(gè)任務(wù)——監(jiān)視器和my_analysis_function(如果分析函數(shù)需要額外的參數(shù),可以通過(guò)提交調(diào)用傳入它們)。
對(duì)fn_thread.result()的調(diào)用將被阻塞,直到分析函數(shù)完成并獲得其結(jié)果,此時(shí)我們可以通知監(jiān)視器停止并獲得最大內(nèi)存。try/finally模塊確保了如果分析函數(shù)拋出異常,內(nèi)存線程仍然會(huì)被終止。
使用這種方法,我們可以有效地隨時(shí)間對(duì)內(nèi)存使用情況進(jìn)行抽樣。大部分工作將在主分析線程中完成;但是每0.1秒,監(jiān)視器線程就會(huì)被喚醒,進(jìn)行一次內(nèi)存測(cè)量,如果內(nèi)存使用量增加就將其存儲(chǔ),然后返回睡眠狀態(tài)。
到此這篇關(guān)于Python實(shí)現(xiàn)監(jiān)視程序的內(nèi)存使用情況的文章就介紹到這了,更多相關(guān)Python監(jiān)視內(nèi)存使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python?matplotlib實(shí)現(xiàn)多子圖布局
多子圖布局是指在一個(gè)圖像中同時(shí)顯示多個(gè)子圖,每個(gè)子圖可以是獨(dú)立的圖形或者是相互關(guān)聯(lián)的圖形,下面我們就來(lái)了解下matplotlib是如何實(shí)現(xiàn)多子圖布局的吧2023-12-12
PyTorch: Softmax多分類實(shí)戰(zhàn)操作
這篇文章主要介紹了PyTorch: Softmax多分類實(shí)戰(zhàn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
Django異步任務(wù)線程池實(shí)現(xiàn)原理
這篇文章主要介紹了Django異步任務(wù)線程池實(shí)現(xiàn)原理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
利用Python找出序列中出現(xiàn)最多的元素示例代碼
這篇文章主要給大家介紹了關(guān)于利用Python找出序列中出現(xiàn)最多的元素的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12
Django contrib auth authenticate函數(shù)源碼解析
這篇文章主要介紹了Django contrib auth authenticate函數(shù)源碼解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
python調(diào)用stitcher類自動(dòng)實(shí)現(xiàn)多個(gè)圖像拼接融合功能
這篇文章主要介紹了python調(diào)用stitcher類自動(dòng)實(shí)現(xiàn)多個(gè)圖像拼接融合功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
python讀取yaml文件后修改寫(xiě)入本地實(shí)例
這篇文章主要介紹了python讀取yaml文件后修改寫(xiě)入本地實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-04-04
python word轉(zhuǎn)pdf代碼實(shí)例
這篇文章主要介紹了python word轉(zhuǎn)pdf代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08

