tracemalloc分析內(nèi)存使用情況與泄露方式
1.概述
python內(nèi)存管理是通過(guò)引用計(jì)數(shù)執(zhí)行的,如果指向某個(gè)對(duì)象的引用全部過(guò)期,那么受引用的對(duì)象就可以從內(nèi)存中清除,從而給其他數(shù)據(jù)騰出空間。
理論上講,python開(kāi)發(fā)不用擔(dān)心程序如何分配和釋放內(nèi)存,因?yàn)閜ython系統(tǒng)本身以及Cpython運(yùn)行環(huán)境會(huì)自動(dòng)處理這些問(wèn)題。
但實(shí)際情況程序會(huì)因?yàn)闆](méi)有及時(shí)釋放不再需要引用的數(shù)據(jù)耗盡內(nèi)存。下面通過(guò)一些方法來(lái)看下內(nèi)存使用情況。
2.查看gc引用對(duì)象總數(shù)
下面是被測(cè)試代碼,這個(gè)代碼可以創(chuàng)建對(duì)象,在gc中產(chǎn)生引用對(duì)象。
import os class MyObject: def __init__(self): self.data = os.urandom(100) def get_data(): values = [] for _ in range(100): obj = MyObject() values.append(obj) return values def run(): deep_values = [] for _ in range(100): deep_values.append(get_data()) return
下面的代碼用來(lái)輸出當(dāng)前gc引用對(duì)象的數(shù)量
import gc # 獲取運(yùn)行前gc引用對(duì)象數(shù)量 found_objects = gc.get_objects() print('Before:', len(found_objects)) # 導(dǎo)入待測(cè)試模塊 import waste_memory # 運(yùn)行待測(cè)試代碼的函數(shù) hold_reference = waste_memory.run() # 獲取運(yùn)行代碼后gc引用對(duì)象數(shù)量 found_objects = gc.get_objects() print('After: ', len(found_objects)) for obj in found_objects[:5]: print(repr(obj)[:100]) print('...')
運(yùn)行上面的代碼,下面是gc引用的對(duì)象總數(shù)。
Before: 28834 After: 28923
3.tracemalloc查看內(nèi)存分配情況
3.1.查看內(nèi)存分配情況
上面只輸出了gc的總數(shù),對(duì)于分析內(nèi)存分配情況沒(méi)有太多的指導(dǎo)意義,tracemalloc模塊能夠追溯到分配它的位置,因此我們可以在之前模塊前后對(duì)內(nèi)存使用情況做個(gè)快照,分析兩個(gè)快照之間的區(qū)別。
下面是被測(cè)試代碼
import tracemalloc tracemalloc.start(10) # Set stack depth time1 = tracemalloc.take_snapshot() # Before snapshot import waste_memory x = waste_memory.run() # Usage to debug time2 = tracemalloc.take_snapshot() # After snapshot stats = time2.compare_to(time1, 'lineno') # Compare snapshots for stat in stats[:3]: print(stat)
運(yùn)行上面的代碼,從結(jié)果中可以看出,每一條記錄都有size與count指標(biāo),用來(lái)表示這行代碼所分配的對(duì)象占用多少內(nèi)存,以及對(duì)象的數(shù)量。
通過(guò)對(duì)比就能發(fā)現(xiàn)占用內(nèi)存較多的對(duì)象是由那幾行代碼分配的。
/waste_memory.py:11: size=5120 B (+5120 B), count=80 (+80), average=64 B /waste_memory.py:14: size=4424 B (+4424 B), count=79 (+79), average=56 B /waste_memory.py:9: size=1704 B (+1704 B), count=8 (+8), average=213 B
3.2.查看棧信息
tracemalloc還可以打印棧的追蹤信息,下面把程序中分配內(nèi)存最多的那行代碼所對(duì)應(yīng)的棧追蹤信息打印出來(lái),看看程序是沿著哪條路徑觸發(fā)這行代碼的。
import tracemalloc tracemalloc.start(10) time1 = tracemalloc.take_snapshot() import waste_memory x = waste_memory.run() time2 = tracemalloc.take_snapshot() stats = time2.compare_to(time1, 'traceback') top = stats[0] print('Biggest offender is:') # 打印棧信息 print('\n'.join(top.traceback.format()))
運(yùn)行上面的代碼
Biggest offender is: File "/with_trace.py", line 14 x = waste_memory.run() File "/waste_memory.py", line 23 deep_values.append(get_data()) File "/waste_memory.py", line 16 obj = MyObject() File "/waste_memory.py", line 11 self.data = os.urandom(100)
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python+OCR實(shí)現(xiàn)文檔解析的示例代碼
本文是一個(gè)簡(jiǎn)單教程,主要介紹了如何使用OCR進(jìn)行文檔解析以及使用Layoutpars軟件包進(jìn)行了整個(gè)檢測(cè)和提取過(guò)程,感興趣的可以了解一下2022-09-09python實(shí)現(xiàn)解數(shù)獨(dú)程序代碼
最近在帶孩子學(xué)習(xí)數(shù)獨(dú),職業(yè)使然,就上網(wǎng)搜了下相關(guān)程序的解法,這里分享給大家,希望對(duì)大家學(xué)習(xí)python有所幫助2017-04-04python解決No?module?named?pip問(wèn)題兩種方法
當(dāng)出現(xiàn)No module named pip錯(cuò)誤時(shí),表明您的Python環(huán)境缺少pip模塊,下面這篇文章主要給大家介紹了關(guān)于python解決No?module?named?pip問(wèn)題的兩種方法,需要的朋友可以參考下2024-01-01python實(shí)現(xiàn)計(jì)數(shù)排序與桶排序?qū)嵗a
這篇文章主要介紹了python計(jì)數(shù)排序與桶排序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03